Forums

Looking for an automated method for plotting the amplitude envelope of an audio signal

Started by maxplanck October 18, 2007
maxplanck wrote:
> Richard Owlett wrote: > > >>Why not following Scilab code: >> >>slope_signal=diff(signal); // simple minded 1st derivative >> // will pass thru 0 at local min/max >>tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >>envelope=abs(signal(tt)); > > > This works great, here is the code that i'm using: > > stacksize(99999999); > signal=fscanfMat('/H1.txt'); > slope_signal=diff(signal); > tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); > envelope=abs(signal(tt)); > plot (tt, envelope); > > However, i'm stumped on the final step here: I need to export the plot > data. (so that i can import it into Reaktor and use it as audio data. > Reaktor can import .txt and .wav files.) > > I've spent a lot of time searching through the scilab help file and > online, looking at many commands hoping to find the one(s) i need. > > Can someone pls give me some guidance here?
The simplistic answer is mfprintf ;/ The gotcha is in _exactly_ what is the set of numbers you need to output. Below is a *PATHOLOGICAL* test case. I don't think it's physically realizable, but it was the easiest way to demonstrate a lurking problem. t=[0:.0001:30]; carrier = 5*sin(100*t); lowersideband = 3*sin(97*t); uppersideband = -7*sin(103.6*t); signal = carrier + lowersideband + uppersideband; slope_signal=diff(signal); // simple minded 1st derivative // will pass thru 0 at local min/max tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); envelope=abs(signal(tt)); delta_t=zeros(tt(1:$-1)); cols=size(delta_t,2); for i=1:cols delta_t(i)=tt(i+1)-tt(i); end plot2d(delta_t)
>maxplanck wrote: >.. >> This works great, here is the code that i'm using: >> >> stacksize(99999999); >> signal=fscanfMat('/H1.txt'); >> slope_signal=diff(signal); >> tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >> envelope=abs(signal(tt)); >> plot (tt, envelope); >> >> However, i'm stumped on the final step here: I need to export the
plot
>> data. (so that i can import it into Reaktor and use it as audio data.
>> Reaktor can import .txt and .wav files.) >> >> I've spent a lot of time searching through the scilab help file and >> online, looking at many commands hoping to find the one(s) i need. >> >> Can someone pls give me some guidance here? > >wavwrite? It is described at the bottom of this page: > >http://www.lumanmagnum.net/physics/sci_wav.html > > >Richard Dobson
I need to do a few things to get my data arranged in a matrix that wavewrite can use. I know what I need to do, but I don't know how to tell scilab to do this (I don't know the syntax.) I've tried looking, but it's such a pain to sort through hundreds of pages of info which is 99.9% stuff that i don't need, looking for the one piece of syntax that i do need. Please if someone can tell me how to tell scilab to do the following (tell me the syntax), it would be such a great help to me: Here is my code so far: stacksize(99999999); signal=fscanfMat('/H1.txt'); //loading the waveform data slope_signal=diff(signal); tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); envelope=abs(signal(tt)); N=0:length(signal); This gives me envelope, which is a 1D matrix containing the amplitudes of each peak in the waveform. tt contains the waveform data index # (i.e. time location) for each element of envelope. What I need to do now, which I need help with the syntax for, is: -draw a line from envelope(1),tt(1) to envelope(2),tt(2), then another line from envelope(2),tt(2) to envelope(3),tt(3), and continue drawing lines this way up to the final line from envelope($-1),tt($-1) to envelope($),tt($). The number of index points that each line should contain should equal tt(endpoint)-tt(startpoint) for that line. The output should consist of one column of values, consisting of the y value of the current line at evenly spaced intervals, and the length of this column should equal length(signal). I know that i probably need to use "linspace" to do this. Here's my best attempt at the syntax for the above algorithm: linenvelope=linspace(envelope(tt(1:odd numbers up to $-1)), envelope(tt(2:(even numbers up to $)), tt(current line's endpoint)-tt(current line's startpoint)); Any help would be much appreciated, i'm really pulling my hair out over this one!
>>maxplanck wrote: >>.. >>> This works great, here is the code that i'm using: >>> >>> stacksize(99999999); >>> signal=fscanfMat('/H1.txt'); >>> slope_signal=diff(signal); >>> tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >>> envelope=abs(signal(tt)); >>> plot (tt, envelope); >>> >>> However, i'm stumped on the final step here: I need to export the >plot >>> data. (so that i can import it into Reaktor and use it as audio
data.
> >>> Reaktor can import .txt and .wav files.) >>> >>> I've spent a lot of time searching through the scilab help file and >>> online, looking at many commands hoping to find the one(s) i need. >>> >>> Can someone pls give me some guidance here? >> >>wavwrite? It is described at the bottom of this page: >> >>http://www.lumanmagnum.net/physics/sci_wav.html >> >> >>Richard Dobson > >I need to do a few things to get my data arranged in a matrix that >wavewrite can use. I know what I need to do, but I don't know how to
tell
>scilab to do this (I don't know the syntax.) > >I've tried looking, but it's such a pain to sort through hundreds of
pages
>of info which is 99.9% stuff that i don't need, looking for the one
piece
>of syntax that i do need. > >Please if someone can tell me how to tell scilab to do the following
(tell
>me the syntax), it would be such a great help to me: > > >Here is my code so far: > >stacksize(99999999); >signal=fscanfMat('/H1.txt'); //loading the waveform data >slope_signal=diff(signal); >tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >envelope=abs(signal(tt)); > >N=0:length(signal); > >This gives me envelope, which is a 1D matrix containing the amplitudes
of
>each peak in the waveform. tt contains the waveform data index # (i.e. >time location) for each element of envelope. > >What I need to do now, which I need help with the syntax for, is: > >-draw a line from envelope(1),tt(1) to envelope(2),tt(2), then another >line from envelope(2),tt(2) to envelope(3),tt(3), and continue drawing >lines this way up to the final line from envelope($-1),tt($-1) to >envelope($),tt($). The number of index points that each line should >contain should equal tt(endpoint)-tt(startpoint) for that line. The >output should consist of one column of values, consisting of the y value >of the current line at evenly spaced intervals, and the length of this >column should equal length(signal). > >I know that i probably need to use "linspace" to do this. Here's my
best
>attempt at the syntax for the above algorithm: > >linenvelope=linspace(envelope(tt(1:odd numbers up to $-1)), >envelope(tt(2:(even numbers up to $)), tt(current line's >endpoint)-tt(current line's startpoint)); > > >Any help would be much appreciated, i'm really pulling my hair out over >this one!
please please please can someone help me here is my best guess: for i=1:(length(envelope)-1), linenvelope2=linspace(envelope(i), envelope(i+1), tt(i+1)-tt(i))'; linenvelope1=cat(1, linenvelope1, linenvelope2); end this shit is driving me crazy
>>maxplanck wrote: >>.. >>> This works great, here is the code that i'm using: >>> >>> stacksize(99999999); >>> signal=fscanfMat('/H1.txt'); >>> slope_signal=diff(signal); >>> tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >>> envelope=abs(signal(tt)); >>> plot (tt, envelope); >>> >>> However, i'm stumped on the final step here: I need to export the >plot >>> data. (so that i can import it into Reaktor and use it as audio
data.
> >>> Reaktor can import .txt and .wav files.) >>> >>> I've spent a lot of time searching through the scilab help file and >>> online, looking at many commands hoping to find the one(s) i need. >>> >>> Can someone pls give me some guidance here? >> >>wavwrite? It is described at the bottom of this page: >> >>http://www.lumanmagnum.net/physics/sci_wav.html >> >> >>Richard Dobson > >I need to do a few things to get my data arranged in a matrix that >wavewrite can use. I know what I need to do, but I don't know how to
tell
>scilab to do this (I don't know the syntax.) > >I've tried looking, but it's such a pain to sort through hundreds of
pages
>of info which is 99.9% stuff that i don't need, looking for the one
piece
>of syntax that i do need. > >Please if someone can tell me how to tell scilab to do the following
(tell
>me the syntax), it would be such a great help to me: > > >Here is my code so far: > >stacksize(99999999); >signal=fscanfMat('/H1.txt'); //loading the waveform data >slope_signal=diff(signal); >tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 ); >envelope=abs(signal(tt)); > >N=0:length(signal); > >This gives me envelope, which is a 1D matrix containing the amplitudes
of
>each peak in the waveform. tt contains the waveform data index # (i.e. >time location) for each element of envelope. > >What I need to do now, which I need help with the syntax for, is: > >-draw a line from envelope(1),tt(1) to envelope(2),tt(2), then another >line from envelope(2),tt(2) to envelope(3),tt(3), and continue drawing >lines this way up to the final line from envelope($-1),tt($-1) to >envelope($),tt($). The number of index points that each line should >contain should equal tt(endpoint)-tt(startpoint) for that line. The >output should consist of one column of values, consisting of the y value >of the current line at evenly spaced intervals, and the length of this >column should equal length(signal). > >I know that i probably need to use "linspace" to do this. Here's my
best
>attempt at the syntax for the above algorithm: > >linenvelope=linspace(envelope(tt(1:odd numbers up to $-1)), >envelope(tt(2:(even numbers up to $)), tt(current line's >endpoint)-tt(current line's startpoint)); > > >Any help would be much appreciated, i'm really pulling my hair out over >this one! >
woops i mean: linenvelope1=linspace(envelope(1), envelope(1), tt(1))'; for i=1:(length(envelope)-1), linenvelope2=linspace(envelope(i), envelope(i+1), tt(i+1)-tt(i))'; linenvelope1=cat(1, linenvelope1, linenvelope2); end but this causes the loop to run forever, i don't know why
I'm using cat in a for loop to concatenate column matrices produced by
the for loop.  The problem is that since i'm working with audio data,
the matrices are long, and cat takes longer every time the for loop
runs because it's handling more data each time the for loop runs.

Are there any alternative functions that i could use instead of cat,
which will be faster?  Perhaps a function that stores a matrix in a
buffer, and when adding elements to that matrix it doesn't have to
process the data that's already in the matrix (i.e. already in the
buffer)?

Thanks, any help would be much appreciated.

Here's my code so far, which takes way too long to run when H1.txt
contains around a second or more of audio data @ 44100 samples/second.

stacksize(99999999);
signal=fscanfMat('/H1.txt');
slope_signal=diff(signal);
tt = find( (slope_signal(1:$-1).*slope_signal(2:$))<= 0 );
envelope=abs(signal(tt));

for i=1:(length(envelope)-1),

        if i == 1 then
                linenvelope = linspace(envelope(i), envelope(i+1),
tt(i+1)-tt(i))';
        else
                linenvelope = cat(1,linenvelope,(linspace(envelope(i),
envelope(i
+1), tt(i+1)-tt(i))'));
        end

end