www.gusucode.com > dsp 案例源码程序 matlab代码 > dsp/DetermineAndDecreaseUnderrunExample.m
%% Determine and Decrease Underrun % _Underrun_ refers to output signal silence, which occurs when the audio % stream loop does not keep pace with the output device. Determine the % underrun of an audio stream loop, add artificial computational load to % the audio stream loop, and then modify properties of your % |audioDeviceWriter| System object(TM) to decrease underrun. Your results % depend on your computer. %% % Create a |dsp.AudioFileReader| System object, and specify the file to % read. Use the |audioinfo| function to return a structure containing % information about the audio file. fileReader = dsp.AudioFileReader('speech_dft.mp3'); fileInfo = audioinfo('speech_dft.mp3'); %% % Create an |audioDeviceWriter| System object. Use the |SampleRate| of the % file reader as the |SampleRate| of the device writer. Call |setup| to % reduce the computational load of initialization in an audio stream loop. deviceWriter = audioDeviceWriter(... 'SampleRate',fileReader.SampleRate); setup(deviceWriter,... zeros(fileReader.SamplesPerFrame,fileInfo.NumChannels)); %% % Run your audio stream loop with input from file and output to device. % Print the total samples underrun and the underrun in seconds. totalUnderrun = 0; while ~isDone(fileReader) input = fileReader(); numUnderrun = deviceWriter(input); totalUnderrun = totalUnderrun + numUnderrun; end fprintf('Total samples underrun: %d.\n',... totalUnderrun); fprintf('Total seconds underrun: %d.\n',... double(totalUnderrun)/double(deviceWriter.SampleRate)); %% % Release your |dsp.AudioFileReader| and |audioDeviceWriter| System objects % and set your counter variable to zero. release(fileReader); release(deviceWriter); totalUnderrun = 0; %% % Use a pause to mimic an algorithm that takes 0.075 seconds to process. % The pause causes the audio stream loop to go slower than the device, % which results in periods of silence in the output audio signal. while ~isDone(fileReader) input = fileReader(); numUnderrun = deviceWriter(input); totalUnderrun = totalUnderrun + numUnderrun; pause(0.075) end fprintf('Total samples underrun: %d.\n',... totalUnderrun); fprintf('Total seconds underrun: %d.\n',... double(totalUnderrun)/double(deviceWriter.SampleRate)); %% % Release your |audioDeviceReader| and |dsp.AudioFileWriter| and set the % counter variable to zero. release(fileReader); release(deviceWriter); totalUnderrun = 0; %% % Set the frame size of your audio stream loop to 2048. Because the % |SupportVariableSizeInput| property of your |audioDeviceWriter| System % object is set to |false|, the buffer size of your audio device is the % same size as the input frame size. Increasing your device buffer size % decreases underrun. fileReader = dsp.AudioFileReader('speech_dft.mp3'); fileReader.SamplesPerFrame = 2048; fileInfo = audioinfo('speech_dft.mp3'); deviceWriter = audioDeviceWriter(... 'SampleRate',fileReader.SampleRate); setup(deviceWriter,... zeros(fileReader.SamplesPerFrame,fileInfo.NumChannels)); %% % Calculate the total underrun. while ~isDone(fileReader) input = fileReader(); numUnderrun = deviceWriter(input); totalUnderrun = totalUnderrun + numUnderrun; pause(0.075) end fprintf('Total samples underrun: %d.\n',... totalUnderrun); fprintf('Total seconds underrun: %d.\n',... double(totalUnderrun)/double(deviceWriter.SampleRate)); %% % The increased frame size reduces the total underrun of your audio stream % loop. However, increasing the frame size also increases latency. Other % approaches to reduce underrun include: % % * Increase the buffer size independent of input frame size. To increase % buffer size independent of input frame size, you must first set % |SupportVariableSizeInput| to |true|. This approach also increases % latency. % % * Decrease the sample rate. Decreasing the sample rate reduces both % latency and underrun at the cost of signal resolution. % % * Choose an optimal driver and device for your system.