I want to create a 30kHz sound with MATLAB ( after which I use the Earthworks microphone ( M50 ) to test / analyse the audio replay (sound) produced from the synthetised signal stored by MATLAB in a .WAV file ).
I use the following code, but whether it is some wrong, and if I want to create another 50kHz wave, how should I modify the code?
Fs = 96200;
toneFreq1 = 30000;
nSeconds = 20;
f1 = sin( linspace( 0, nSeconds*toneFreq1*2*pi, round( nSeconds * Fs ) ) );
sound( f1, Fs )
wavwrite( f1, Fs, 24, '30khz.wav' );
First, most soundcards are not able to play back using your Fs. Typically, they offer 88200 or 96000 Hz, so you should choose one of them.
Second, due to Nyquist-Shannon theorem you can't create a frequency higher than half the sampling rate. I.e. with Fs=96000 the highest possible frequency is theoretically 48000 Hz, but then you need to use cos instead of sin.
Update: You are creating, playing back, recording, and analysing a sound. So, you have various sources of error.
My two points above correct your problems with creating the sound. The following matlab program shows clearly that the synthetic signal comprises exactly the sine wav you intended to create. So, the problem your original question was about, is solved:
clear
Fs = 96000;
toneFreq1 = 30000; % change between 0 and Fs/2=48000
nSeconds = 20;
f1 = cos( linspace (0, nSeconds*toneFreq1*2*pi, round(nSeconds*Fs) ) );
freqz( f1, length(f1) )
Thus, the new spectrogram image of your modified question reflects other problems that are due to playing back, recording, and/or analysing.
It is hard to say, what problem you face. I just can give you some hints:
1) Most probable, your amplifier and/or loudspeaker are not able to reproduce frequencies much above 20kHz. You should start with frequencies between 8 and 12kHz, then you are able to hear them. If you are older than, say 40 years, it could be hard for you to hear frequencies above ca. 15kHz. But even if you are 20 years old you're not able to hear frequencies above ca. 18 to 20kHz (at least you need huge amplification to hear them).
2) Your microphone is able to convert these high frequencies into an electrical signal, but it is possible that either your microphone amplifier or your sound card is bandwidth-limited to say 22 or 24kHz.
3) Your program that converts the measured signal into a spectrogram might have bugs.
4) The segmentation at the beginning and end of the measured signal also introduces artifacts into the spectrum.
If you need further help, you should post your recording and analysis code. But I guess that with my hints you are able to find the problem on your own. Nonetheless, it would be interesting to inform us about your results.
Related
I'm a novice MATLAB user, so apologies if the question is very basic. I need a .wav sound file to be played in a single, specific channel -- let's say the left channel. As it is, my code reads in the sound file, and I add in a column of zeros to nullify the channel I don't want, like so:
currentDir = pwd;
soundFile = [currentDir '\sound1.wav']; % load the file
[y, Fs] = audioread(soundFile); % read the file in
soundData(:,1) = y(:,1); % keeps sound for the left channel
soundData(:,2) = 0; % nullifies the right channel
sound = audioplayer(soundData,Fs);
play(sound);
As it stands, the code currently produces a sound that is full volume in the left speaker, and half volume (but still very much audible) in the right speaker. I have tried this with at least 20 .wav files, with the same result.
In case it's relevant, this happens even when I write in code that explicitly matches the length of the sound variable in 0s, like so:
[y, Fs] = audioread(soundFile);
silentChannel = zeros(size(y));
soundData(:,1) = y(:,1); % keeps sound for the left channel
soundData(:,2) = silentChannel(:,2); % nullifies the right channel
Does anybody know what I'm doing wrong, or have any thoughts?
Your code is definitely correct and it should only play audio in the left channel. I suspect that the problem is caused by a sound-card/driver issues. Allow me suggest the following troubleshooting steps:
Save your output as a wav file using audiowrite('output.wav', soundData, Fs). Play this using a different audio player, such as Audacity. If you still hear output in both channels, it must be a sound-card/driver issue.
Assuming that you are using a Windows PC (going by the syntax in your file path), make sure all sound enhancements are disabled. How to do this depends on the PC. If there is a third-party app controlling the playback settings, you'd have to use that. Otherwise find the settings shown in the picture below in the Control Panel.
In MatLab the expected method for playing sound is the method sound(data,Fs)
To control the channel the sound emits on, you'll want to know how sound() reads data.
data is a matrix with the columns representing channels, and with the rows holding the samples of the waveform for a given sampling fequency Fs
here is a simple implementation.
function treismanwolfe()
close all
clear all
clc
Fs = 40000;
tau = 2*pi();
t = 0:tau/(Fs-1):tau/2;
left = sin(t).*(sin(t*200)+sin(t*1600));
left= left/max(abs(left));
left = left'; %turn column vector into row
right = sin(t).*(sin(t*800)+sin(t*400));
right= right/max(abs(right));
right = right'; %turn column vector into row
data = [left,right*0]; %multiply either by 0 to nullify
sound(data,Fs); %so you can hear it.
end
I hope this works for you. Enjoy!
When I run your code the audio output is only audible in the left channel as you have specified.
#Austin Kootz' version with the sound()-function is just as good and also produces what you're looking for, but with audioplayer-object you have the ability to stop the playback in the middle of the playback (as you probably know)
Have you tried converting your .wav to another format to see if that makes a change?
I am trying to create an experiment on psychtoolbox and one part of it involves sounding an alarm when the participant fail to respond.
I tried using the beep provided but it does not sound like an alarm at all. Is there any way to achieve that without having to download a external sound?
I have no knowledge of sound or sound waves so please help!
The following code will load a .wav file, and play it through the Psychtoolbox audio system. This allows you to have a timestamp of sound onset, and allows greater control than using sound() or beep. You could alternatively generate a tone using MATLAB itself (it is easy to generate a sine wave of a particular frequency) and use that instead of the .wav data.
%% this block only needs to be performed once, at the start of the experiment
% initialize the Psychtoolbox audio system in low latency mode
InitializePsychSound(1);
% load in a waveform for the warning
[waveform,Fs] = audioread('alarm.wav');
numChannels = size(waveform, 2);
% open the first audio device in low-latency, stereo mode
% if you have more than one device attached, you will need to specify the
% appropriate deviceid
pahandle = PsychPortAudio('Open', 2, [], 1, Fs, numChannels);
%% during the experiment, when you want to play the alarm
PsychPortAudio('FillBuffer', pahandle, waveform' );
startTime = PsychPortAudio('Start', pahandle, 1);
%% at the conclusion of the experiment
PsychPortAudio('Close');
If you'd like to generate your own sound, take a look at the Psychtoolbox function 'MakeBeep', and substitute that in, instead of the waveform, for example, a 1000 Hz tone, lasting 250ms, at a 44.1k sampling rate:
% generate a beep
beepWaveform = MakeBeep(1000,.250,44100);
% make stereo
beepWaveform = repmat(beepWaveform, 2, 1);
% fill buffer, play
PsychPortAudio('FillBuffer', pahandle, beepWaveform );
startTime = PsychPortAudio('Start', pahandle, 1);
To me, beep can do what you want by playing it multiple times in the loop like this:
% Adjust the no. of loop iterations depending on how long you want to play the alarm
for k=1:100
beep; pause(1);
end
Other than that, you can use built-in sounds like this:
load('gong'); % This sound seems suitable to me for alarm. Try others from the list
for k=1:100
sound(y,Fs); pause(1);
end
Here's a list of built-in sounds that you may want to try:
chirp
gong
handel
laughter
splat
train
I have a couple of audio files that want to normalize at .-1dB, any idea how may I do that.
PS: I'm not asking how to read them, consider they are all saved in the Workspace as : A1 A2 A3 etc
UPDATE
thanks to Neil for his comment, here an example of two files , as you can see the signal aren't on the same level , ( that causes problems when try to any their PSD, so I would like to get all the file at the same level as far I know that called normalization. I can do that in Audacity but not in Matlab, because I don't know and the mathematics behind it.
thanks for your help
Normalising an audio waveform involves:
Choosing the desired norm. You have more choices than just the maximum offset, but that is the simplest. If your representation is sample values in range -1.0 to 1.0, then normalising to -1dB is actually saying you want all values to be between -0.891 and 0.891 (from Wikipedia article on Decibel)
Finding the current absolute maximum value. You can use e.g. max(abs( A1(:) ) ) for that
Multiplying all values such that the maximum is now limited to the new top value. Multiplication is the correct operation due to the representation used by most raw audio signals.
So, in theory, you want something like:
A1_norm = A1 * 0.891 / max( abs( A1(:) ) );
We were recently taught the concepts of error control coding - basic codes such as Hamming code, repeatition code etc.
I thought of trying out these concepts in MATLAB. My goal was to compare how an audio file plays when corrupted by noise and in the case when the file is protected by basic codes and then corrupted by noise.
So I opened a small audio clip of 20-30 seconds in MATLAB using audioread function. I used 16 bit encoded PCM wave file.
If opened in 'native' format it is in int16 format . If not it opens in a double format.
I then added two types of noises to it : - AWGN noise (using double format) and Binary Symmetric Channel noise (by converting the int16 to uint16 and then by converting that to binary using dec2bin function). Reconverting back to the original int16 format does add a lot of noise to it.
Now my goal is to try out a basic repeatition code. So what I did was to convert the 2-d audio file matrix which consists of binary data into a 3-d matrix by adding redundancy. I used the following command : -
cat(3,x,x,x,x,x) ;
It created a 3-D matrix such that it had 5 versions of x along the 3rd dimension.
Now I wish to add noise to it using bsc function.
Then I wish to do the decoding of the redundant data by removing the repetition bits using a mode() function on the vector which contains the redundant bits.
My whole problem in this task is that MATLAB is taking too long to do the computation. I guess a 30 second file creates quite a big matrix so maybe its taking time. Moreover I suspect what I am doing is not the most efficient way to do it with regards to the various data types.
Can you suggest a way in which I may improve on the computation times. Are there some functions which can help do this basic task in a better way.
Thanks.
(first post on this site with respect to MATLAB so bear with me if the posting format is not upto the mark.)
Edit - posting the code here :-
[x,Fs] = audioread('sample.wav','native'); % native loads it in int16 format , Fs of sample is 44 khz , size of x is 1796365x1
x1 = x - min(x); % to make all values non negative
s = dec2bin(x); % this makes s as a 1796365x15 matrix the binary stream stored as character string of length 15. BSC channel needs double as the data type
s1 = double(s) - 48; % to get 0s and 1s in double format
%% Now I wish to compare how noise affects s1 itself or to a matrix which is error control coded.
s2 = bsc(s,0.15); % this adds errors with probability of 0.15
s3 = cat(3,s,s,s,s,s) ; % the goal here is to add repetition redundancy. I will try out other efficient codes such as Hamming Code later.
s4 = bsc(s3,0.15);% this step is taking forever and my PC is unresponsive because of this one.
s5 = mode(s4(,,:)) ; % i wish to know if this is a proper syntax, what I want to do is calculate mode along the 3rd dimension just to remove redundancy and thereby reduce error.
%% i will show what I did after s was corrupted by bsc errors in s2,
d = char(s2 + 48);
d1 = bin2dec(d) + min(x);
sound(d1,Fs); % this plays the noisy file. I wish to do the same with error control coded matrix but as I said in a previous step it is highly unresponsive.
I suppose what is mostly wrong with my task is that I took a large sampling rate and hence the vector was very big.
I'm trying to extract information from a sound file in order to use it in a video classification algorithm I'm working on.
My problem is that I don't know how to work exactly with audio files in Matlab.
Below is what I need to accomplish:
open the audio file and get the sampling rate/frequency
I need to work on a window of 2 seconds so I have to loop over the file and get each 2 seconds as a window and then do the ftt (Fast-Fourier-Transform) on each window.
After that it is my turn to use these values to do what I want
any help would be appreciated
Thanks.
Following code may only give you some idea. You may need to determine another fft size, a windowing function like hamming etc.
To read a wav file:
[data, Fs] = wavread('path.wav');
Splitting to 2 sec windows and getting fft:
frameFFT = [];
timeStep = Fs*2;
for i=1:timeStep:length(data)-timeStep
frameFFT = [frameFFT; fft(data(i:i+timeStep-1),1024)];
end