プロジェクトの進め方がわからず困っています。手短に言えば、加速度計からのデータを使用して FM シンセサイザーを作成し、FM およびピッチのパラメーターをリアルタイムで変更しようとしています。
これが私がそれに基づいているコードのいくつかです:
% X axis data will be used for fc parameter
% Y axis data will be used for fm parameter
function y = fmSynth(fc, dur, fm)
fs = 48000;
T = 1/fs; % seconds
t = 0:T:dur; % time vector
% FM parameters
Imin = 0;
Imax = 20;
I = t.*(Imax - Imin)/dur + Imin;
y = sin(2*pi*fc*t + I.*sin(2*pi*fm*t));
plot(t(1:10000), y(1:10000));
sound(y, fs);
波を生成する関数がありますが、設定された期間のみです (組み込みの matlab 関数の制限のため)。私はそれを(そのようなユーザー入力が停止するまで)連続させ、「リアルタイム」で変調できるようにしたいと思います(少しの遅れは問題ありません)。
これについては、ここでリアルタイム オーディオ プロセッサ コードを見つけました。
ただし、これはオブジェクト指向プログラミング言語で書かれており、私にはなじみがありません。
上記の関数をこのコード (出力 rtap) に実装する簡単な方法はありますか、それともサブクラスに記述する必要がありますか? もしそうなら、どのように?
コードをダウンロードしたくない人のために、主なクラスは次のとおりです。
% RealTimeAudioProcessor
%
% The RealTimeAudioProcessor object allows the user to process consecutive
% frames of audio in real-time (it lags real-time by the frame size plus
% hardware overhead). The object can easily be extended for any type of
% audio processing by overloading the stepImpl method in a derived class.
%
% Use:
%
% % Create the processor with a number of input channels, number of output
% % channels, sample rate, frame size, and device name.
% rtap = RealTimeAudioProcessor(1, 2, 48000, 256, 'Default');
%
% % Play. This will start *immediately* and block until all audio output is
% % complete.
% rtap.Play();
%
% % Release the audio resource for others (be nice).
% rtap.release();
%
% % The RTAP records some timing values while playing. Show the results.
% rtap.Analyze();
%
% It is recommended that an ASIO audio driver with appropriate hardware be
% used for the audio interface. (ASIO is an open standard from Steinberg
% Media Technologies GmbH).
%
% Tucker McClure @ The MathWorks
% Copyright 2012 The MathWorks, Inc.
classdef RealTimeAudioProcessor < matlab.system.System
properties (Nontunable, Access = protected)
% Settings
frame_size = 256; % Number of samples in the buffer
sample_rate = 48000; % Number of samples per second [samples/s]
end_time = inf; % Number of seconds until playback stops [s]
in_channels = 2; % Number of input channels
out_channels = 2; % Number of output channels
device_name = 'Default';
draw_rate = 0.02; % Rate to update graphics [s]
% Derived quantities
time_step; % Length of frame [s]
time_window; % Array of time values from [0 time_step) [s]
% Device interfaces
ap; % AudioPlayer object to manage output
ar; % AudioRecorder object to manage input
end
properties
% UI handles
figure_handle; % Handle of UI figure
text_handle; % Handle of text in figure
samples_until_draw = 0; % Samples left before updating GUI
% Analysis stuff
max_in_step_time = 0;
max_process_step_time = 0;
max_out_step_time = 0;
end
methods
% Constructor; creates the RTAP and its internal dsp.AudioPlayer.
% After creation, the RTAP is ready to play.
function rtap = RealTimeAudioProcessor(ins, outs, Fs, w, device)
fprintf('Initializing a RealTimeAudioProcessor on %s... ', ...
device);
% Set some internals.
rtap.frame_size = w;
rtap.sample_rate = Fs;
rtap.in_channels = ins;
rtap.out_channels = outs;
rtap.device_name = device;
% Calculate the period.
rtap.time_step = w/Fs;
% Create all the time values for a window.
rtap.time_window = (0:w-1)'/Fs;
% Ok, we set everything up.
fprintf('done.\n');
% Display latency to user.
fprintf('Minimum latency due to buffering: %5.1fms\n', ...
1000 * rtap.time_step);
end
% Enter a quasi-real-time loop in which audio is acquired/generated
% and plugged into the output buffer (if a buffer exists).
function Play(rtap)
% If not set up, setup.
if ~rtap.isLocked
setup(rtap, ...
zeros(rtap.frame_size, 1), ...
zeros(rtap.frame_size, rtap.in_channels));
% Otherwise, if we need a new figure, open one.
elseif ~ishandle(rtap.figure_handle)
rtap.GenerateFigure();
end
% Keep track of time since 'tic'.
t_clock = 0;
% Keep track of how much material we've played since 'tic'.
% At t_clock, this should reach to t_clock + time_step.
t_played = 0;
% Initialize the input.
in = zeros(rtap.frame_size, rtap.in_channels); %#ok<NASGU>
% Start a timer.
tic();
% Loop until the end time has been reached or the figure has
% been closed.
while t_clock < rtap.end_time && ishandle(rtap.figure_handle)
% Play steps until we're |buffer| into the future.
if t_played < t_clock + rtap.time_step
% Create the times for this frame.
time = t_played + rtap.time_window;
% Get the input for one frame.
if rtap.in_channels > 0
step_timer = tic();
in = step(rtap.ar);
rtap.max_in_step_time = ...
max(rtap.max_in_step_time, toc(step_timer));
else
in = zeros(rtap.frame_size, rtap.in_channels);
end
% Process one frame.
step_timer = tic();
out = step(rtap, time, in);
rtap.max_process_step_time = ...
max(rtap.max_process_step_time, toc(step_timer));
% Step the AudioPlayer. Time the step for analysis
% purposes.
if rtap.out_channels > 0
step_timer = tic();
step(rtap.ap, out);
rtap.max_out_step_time = ...
max(rtap.max_out_step_time, toc(step_timer));
end
% Update the time.
t_played = t_played + rtap.time_step;
end
% Release focus so that figure callbacks can occur.
if rtap.samples_until_draw <= 0
drawnow();
rtap.UpdateGraphics();
rtap.samples_until_draw = ...
rtap.sample_rate * rtap.draw_rate;
else
rtap.samples_until_draw = ...
rtap.samples_until_draw - rtap.frame_size;
end
% Update the clock.
t_clock = toc();
end
% Wait for audio to end before exiting. We may have just
% written out a frame, and there may have already been a frame
% in the buffer, so chill for 2 frames.
pause(2*rtap.time_step);
end
% Display timing results from last play.
function Analyze(rtap)
fprintf(['Results for last play:\n', ...
'Maximum input step time: %5.1fms\n', ...
'Maximum process step time: %5.1fms\n', ...
'Maximum output step time: %5.1fms\n'], ...
1000*rtap.max_in_step_time, ...
1000*rtap.max_process_step_time, ...
1000*rtap.max_out_step_time);
end
end
methods (Access = protected)
% Set up the internal System Objects and the figure.
function setupImpl(rtap, ~, ~)
% Create the AudioPlayer.
if rtap.out_channels > 0
rtap.ap = dsp.AudioPlayer(...
'DeviceName', rtap.device_name, ...
'BufferSizeSource', 'Property', ...
'BufferSize', rtap.frame_size, ...
'QueueDuration', 0, ...
'SampleRate', rtap.sample_rate);
% Start with silence. This initializes the AudioPlayer to
% the window size and number of channels and takes longer
% than any subsequent call will take.
step(rtap.ap, zeros(rtap.frame_size, rtap.out_channels));
end
% Create the AudioRecorder (if requested).
if rtap.in_channels > 0
rtap.ar = dsp.AudioRecorder(...
'DeviceName', 'Default', ...
'SampleRate', rtap.sample_rate, ...
'BufferSizeSource', 'Property', ...
'BufferSize', rtap.frame_size, ...
'SamplesPerFrame', rtap.frame_size, ...
'QueueDuration', 0, ...
'OutputDataType', 'double', ...
'NumChannels', rtap.in_channels);
% Initialize the input.
step(rtap.ar);
end
if ishandle(rtap.figure_handle)
close(rtap.figure_handle);
end
rtap.GenerateFigure();
% Draw it.
drawnow();
% Chill out for a second before rushing forward with sound.
pause(rtap.time_step);
end
% Process one frame of audio, given the inputs corresponding to the
% frame and the times.
function out = stepImpl(rtap, time, in) %#ok<INUSD>
out = zeros(rtap.frame_size, rtap.out_channels);
end
% Specify that the step requires 2 inputs.
function n = getNumInputsImpl(~)
n = 2;
end
% Specify that the step requires 1 output.
function n = getNumOutputsImpl(~)
n = 1;
end
% Clean up the AudioPlayer.
function releaseImpl(rtap)
% Release the dsp.AudioPlayer resource.
if rtap.out_channels > 0
release(rtap.ap);
end
% Release the dsp.AudioRecorder too.
if rtap.in_channels > 0
release(rtap.ar);
end
% Close the figure if it's still open.
if ishandle(rtap.figure_handle)
set(rtap.text_handle, 'String', 'Closing.');
close(rtap.figure_handle);
rtap.figure_handle = [];
end
end
% Generate a figure that stays open with updates for the user.
% Closing this figure ends playback.
function GenerateFigure(rtap)
% Get the screen dimensions for centering the figure.
screen_dims = get(0, 'ScreenSize');
figure_width_height = [640 160];
figure_dims = [floor(0.5*( screen_dims(3:4) ...
- figure_width_height)) ...
figure_width_height];
% Generate a figure.
rtap.figure_handle = figure(...
'Name', 'Real-Time Audio Processor Controller',...
'NumberTitle', 'off', ...
'Position', figure_dims);
axes('Position', [0 0 1 1], ...
'Visible', 'off');
rtap.text_handle = text(0.5, 0.5, ...
'Real Time Audio Processor is active.', ...
'HorizontalAlignment', 'center', ...
'VerticalAlignment', 'middle', ...
'Interpreter', 'none');
end
function UpdateGraphics(rtap) %#ok<*MANU>
end
end
end
パッケージにはサンプルとして使用されている他のファイルもありますが、それらをうまく変更できませんでした。さらに、加速度計データの読み取りとフィルタリングのコードを投稿していないことをお詫びします (少し長いです)。