How to dynamically change a sine wave sound frequency ?

10 visualizaciones (últimos 30 días)
Pierre Musacchio
Pierre Musacchio el 18 de Mayo de 2021
Comentada: Geoff Hayes el 19 de Mayo de 2021
Hello everyone.
I'm currently programming an application which goal is to generate audio sine waves such that frequencies increase or decrease over time.
However the user should be able to use up and down keys in order to counter this drift.
For example : if the frequency is decreasing over time, the user should be able to press the up key to increase it dynamically.
The thing is I can't find any information on how to to such a thing. I've been using the
soundsc(audio, fs)
function which allows to play a sound at a given sample rate, but I always must create the sine wave before feeding it to the function which leaves no room for dynamic variations.
Is it possible to do this in Matlab ? If so, what function allows you to make this ? If there is no function for that, how should I proceed ?
Here is my current code if you want to take a look at it :
% soundTesting.m
fs = 16000;
s = generateWave(400, 1, fs, 5);
t = generateTarget(800, 1, fs, 5, 0.5);
audio = [s; t]';
% Playing audio in stereo with target audio on the right speaker and drifting sine wave on the left
% Note that for now the sine wave is not drifting at all.
soundsc(audio, fs);
%generateWave.m
function wave = generateWave(frequency, amplitude, fs, length)
ts = 1 / fs;
t = 0 : ts : length;
wave = amplitude * sin(2 * pi * frequency * t);
end
%generateTarget.m
function target = generateTarget(frequency, amplitude, fs, length, span)
wave = generateWave(frequency, amplitude, fs, length);
target = zeros(size(wave));
for i = 1 : length - 1
% Every second, emit the target sound for span seconds.
target(i * fs : i * fs + int32(span * fs)) = wave(i * fs : i * fs + int32(span * fs));
end
end
I thougt about trying to create multiple audios and shifting the frequency over time so I wrote this code. However, killing the first signal in order to play a second one is not a smooth operation. Indeed, there is a blank right after the first sound is cleared...
fs = 16000;
s = generateWave(400, 1, fs, 5);
t = generateTarget(800, 1, fs, 5, 0.5);
audio = buildStereo(s, t); % Simply creates a matrix containing s and t so that it can be played in stereo
s2 = generateWave(1200, 1, fs, 5);
audio2 = buildStereo(s2, t);
soundsc(audio, fs);
pause(2)
clear sound % Not smooth, there is a blank right after the first sound is cleared
soundsc(audio2, fs)
Thank you very much.

Respuesta aceptada

Geoff Hayes
Geoff Hayes el 18 de Mayo de 2021
Pierre - I don't think you can dynamically change the frequency even if using the audioplayer. I think that you could use one player and wait for it to stop before applying the frequency change and then restart the player so that it plays at the new frequency. For example, the following code will play a signal at an initial frequency and continue to play it (at that frequencey or another) until the user stops (by pressing 'x').
function AudioPlayerFrequencyExample
close all;
% initialize the audioplayer
durationSec = 2;
Fs = 8000;
t = linspace(0,durationSec,durationSec*Fs);
frqHz = 100;
Y = sin(2*pi*frqHz*t);
audioPlayer1 = audioplayer(Y,Fs);
stopAudioForAlways = false;
freqDeltaHz = 0;
% create the figure and assign the callback
hFig = figure;
set(hFig,'WindowKeyPressFcn',@keyPressCallback);
function keyPressCallback(~,eventdata)
% start the player if needed
if ~isplaying(audioPlayer1)
restartAudioPlayerIfStopped();
end
% determine the key that was pressed
keyPressed = eventdata.Key;
if strcmpi(keyPressed,'uparrow')
% increase the frequency by 10 Hz
freqDeltaHz = 10;
elseif strcmpi(keyPressed,'downarrow')
% decrease the frequency by 10 Hz
freqDeltaHz = -10;
elseif strcmpi(keyPressed,'x')
% stop the player
stopAudioForAlways = true;
end
end
function restartAudioPlayerIfStopped(~, ~)
% restart the player at the (possibly) new frequency
if ~stopAudioForAlways
frqHz = frqHz + freqDeltaHz;
Y = sin(2*pi*frqHz*t);
freqDeltaHz = 0;
audioPlayer1 = audioplayer(Y,Fs);
audioPlayer1.StopFcn = @restartAudioPlayerIfStopped;
play(audioPlayer1);
end
end
end
Note that there is a pause when the player stops and then restarts at a different frequency. I tried experimenting with two players so that I could start one and then stop the running player but noticed a clicking (static) sound during the transition.
  2 comentarios
Pierre Musacchio
Pierre Musacchio el 19 de Mayo de 2021
Thank you very much for your answer Geoff, so if I understand correctly it might be impossible to even create the illusion of continuity, even using two players ?
Geoff Hayes
Geoff Hayes el 19 de Mayo de 2021
Hii Pierre - yes, with two players on my Macbook, I had difficulty creating a seamless change in frequency. I don't have the Audio Toolbox but perhaps something can be used here (if you have this toolbox). The Real-Time Parameter Tuning may offer something interesting.

Iniciar sesión para comentar.

Más respuestas (0)

Productos


Versión

R2014a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by