💾 Archived View for heavysquare.com › noise › 1000-00-00-splitting-on-beeps.txt captured on 2023-04-19 at 23:10:50.

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-


The tools I used were: [sox](http://sox.sourceforge.net/) and
[octave](https://www.gnu.org/software/octave/).

The first step is to somehow create a textual data of your wave file
with sox. Sox supports this by default, you could do something like
this with the following command

    sox -S file.wav file.dat

This can be huge, but managable nowadays (10-15 times the size of the wave file).
As a next step you have to prepare this file to be parsable by octave.

    sed -i '1,2 d' file.dat
    LEN=`cat file.dat | wc -l`
    cat >matrix.txt <<EOF
    # Created by X
    # name: wave
    # rows: $LEN
    # columns: 3
    EOF
    cat file.dat >> matrix.txt
    rm file.dat
    octave

The columns for me was 3 as it was a stereo file (first column is time). The
first two lines removed from file.dat are not data. After this you could go
to octave and do a spectrogram.

    load -text "matrix.txt" 
    n=128
    window=hanning(n);
    Fs=44100
    overlap = length(window)/2
    win_size = length(window)
    step = win_size - overlap
    offset = [1:step:length(wave)-win_size];
    S=zeros(n,length(offset));
    for i=1:length(offset)
      S(1:win_size,i)=wave(offset(i):offset(i)+win_size-1,2) .*     window;
    end
    S = fft(S);
    ret_n = n/2
    S=S(1:ret_n,:);
    imagesc (20*log10(flipud(abs(S))));


![spectro1](/im/spectro1.jpg "full")

You will see a spectrogram like the one above. You could certainly spot the places
where the beep sounds. Hover your mouse on one of the beeps, and read the column. In
case it is too long, you could just plot one slice of your data as follows

    imagesc (20*log10(flipud(abs(S(:,2000:5000)))));

![spectro2](/im/spectro2.jpg "slice")

You can see that the middle of my beep was at 1000 on the second plot, which makes
column 3000 a good pattern for the beep frequency distribution. Now you can just
subtract this from your data and sum up the frequency energies to get some plot of
the beeps:

    beepcol=3000
    Sabs=abs(S);
    beeper=repmat(Sabs(:,beepcol),1,length(Sabs));
    Sbeep=abs(Sabs - beeper);
    energysum=sum(Sbeep);
    plot(energysum)

![energy](/im/energy.jpg "energy")

From this third plot, the thing you have to read is a good threshold which separates
data and beep. For me, 35 seems to be perfect. With this value you can construct the
series of intervals that represent the data between the beeps.

    cutter=35
    needed=(energysum > cutter);
    intervals=[]
    if needed(1)==1
      intervals=[1,-1];
    end
    
    for i=2:length(needed)
      if needed(i-1)==1 && needed(i)==0
        intervals(1,2)=i;
      end
      if needed(i-1)==0 && needed(i)==1
        intervals=[i,-1;intervals];
      end
    end
    
    if intervals(1,2)==-1
      intervals(1,2)=length(needed);
    end
    
    intervals=(intervals*overlap)/Fs;
    intervals=[intervals(:,1),intervals(:,2)-intervals(:,1)];
    save -text "intervals.txt" intervals
    exit

Now you have your list of intervals, you could use your shell and sox to automate
the extraction of data, something like this:

    % tac intervals.txt| sed -n '/^ / p' | head -4
     0.00145124716553288 4.003990929705216
     5.259319727891157 2.461315192743764
     8.974512471655329 1.497687074829932
     11.72607709750567 2.182675736961452
    % tac intervals.txt | sed -n '/^ / p' | \
      head -1 | xargs sox file out1.wav trim

That's it.