-odac
sr = 48000
ksmps = 64
nchnls = 2
0dbfs = 1
seed 0
/*
play any file mono; just take left channel of stereo
aout playmono Sfile
aout output
Sfile path to audio file
*/
opcode playmono, a, S
Sfile xin
if (filenchnls(Sfile) == 1) then
aout diskin Sfile
else
aout, a_ diskin Sfile
endif
xout aout
endop
/*
analyse a file, splitting into segments based on a threshold, and return three arrays of information.
the first index of each array corresponds to each other.
kdone, ktimes[][], kpitches[][], kcentroids[][], kmaxindex analyse Sfile
kdone trigger to specify when analysis has completed
ktimes[][] segment times : start and end
kpitches[][] pitches: min, max and mean
kcentroids[][] centroids: min, max and mean
kmaxindex maximum index of the arrays (ie, corresponding to number of events)
irmsthreshold threshold/ratio
iminsegmenttime minimum segment time in seconds
*/
opcode analyse, kk[]k[]k[]k, Sii
Sfile, irmsthreshold, iminsegmenttime xin
; minimum and maximum frequency range for analysis
ipitchmin = 50
ipitchmax = 8000
; k-cycle tracking
ktimek timeinstk
; output arrays: initialise large to account for many entries
ktimes[][] init 999999, 2
kpitches[][] init 999999, 3
kcentroids[][] init 999999, 3
kdone init 0
kactive init 0
kindex init 0
kstart init 0
; runtime pitch and centroid min/max tracking
kpitchrange[] fillarray ipitchmax, ipitchmin
kcentroidrange[] fillarray ipitchmax, ipitchmin
; k-cycle count for rms threshold partitioned segments
keventcount init 0
; totals for averaging
kpitchtotal init 0
kcentroidtotal init 0
krmstotal init 0
; rms values for total file overview
kavgrms init 0
kminrms init 1
kmaxrms init 0
; k-cycle 1: go through the entire file and determine min, max and mean rms
if (ktimek == 1) then
; how long to run
ilen filelen Sfile
kcycles = ilen * kr
kcount init 0
looprms:
; read the file and extract rms
asig playmono Sfile
krms rms asig
krmstotal += krms
; check if rms is greater or less than range already known and store accordingly
if (krms > kmaxrms) then
kmaxrms = krms
endif
if (krms < kminrms) then
kminrms = krms
endif
; continue through file
loop_lt kcount, 1, kcycles, looprms
; determine mean
kavgrms = krmstotal / kcount
; k-cycle 2: when rms is above a specific threshold (ratio of average rms determined above), extract pitch, centroid and times
elseif (ktimek == 2) then
;kthresh = kavgrms * irmsthreshold
kthresh = kmaxrms * irmsthreshold
; how long to run
ilen filelen Sfile
kcycles = ilen * kr
kcount = 0
loopanalysis:
; read the file and extract pitch, rms and centroid
asig playmono Sfile
kcps, krms pitchamdf asig, ipitchmin, ipitchmax
kcentroid centroid asig, 1, 1024
; if the rms is above our threshold
if (krms > kthresh) then
; ... and we are not already analysing, then reset analysis measures and start analysing the segment
if (kactive == 0) then
keventcount = 0
krunningtotal = 0
kactive = 1
kstart = kcount / kr
kpitchrange[0] = ipitchmax
kpitchrange[1] = ipitchmin
kcentroidrange[0] = ipitchmax
kcentroidrange[1] = ipitchmin
kcentroidtotal = 0
kpitchtotal = 0
endif
; otherwise, analysis of the current segment continues
; check if pitch or centroid is greater or less than range already known and store accordingly
if (kcps > kpitchrange[1]) then
kpitchrange[1] = kcps
endif
if (kcps < kpitchrange[0]) then
kpitchrange[0] = kcps
endif
if (kcentroid > kcentroidrange[1]) then
kcentroidrange[1] = kcentroid
endif
if (kcentroid < kcentroidrange[0]) then
kcentroidrange[0] = kcentroid
endif
; add centroid and pitch for later averaging
kcentroidtotal += kcentroid
kpitchtotal += kcps
; increment k-cycle for current segment
keventcount += 1
; if the rms is below our threshold
else
; ... and we are analysing, then stop doing so and store the min/max/avg pitches and centroids along with start/end times
if (kactive == 1 && (keventcount / kr) > iminsegmenttime) then
ktimes[kindex][0] = kstart
ktimes[kindex][1] = kcount / kr
kpitches[kindex][0] = kpitchrange[0]
kpitches[kindex][1] = kpitchrange[1]
kpitches[kindex][2] = kpitchtotal / keventcount
kcentroids[kindex][0] = kcentroidrange[0]
kcentroids[kindex][1] = kcentroidrange[1]
kcentroids[kindex][2] = kcentroidtotal / keventcount
kindex += 1
kactive = 0
endif
; if we are not currently analysing, then nothing else to do
endif
; continue through file
loop_lt kcount, 1, kcycles, loopanalysis
; k-cycle 3: complete
elseif (ktimek == 3) then
kdone = 1
endif
xout kdone, ktimes, kpitches, kcentroids, kindex
endop
/*
example analysis
*/
instr analyse
; get the analysis data
kdone, ktimes[], kpitches[], kcentroids[], kmaxindex analyse "/tmp/text.wav", 0.01, 1
; when done, print out some data
if (kdone == 1) then
printf "\n\n\nResults:\n", 1
kindex = 0
while (kindex < kmaxindex) do
printf "Start: %f ; End: %f ; Pitch min: %f, max: %f, avg: %f ; Centroid min: %f, max: %f, avg: %f\n", kindex+1,\
ktimes[kindex][0], ktimes[kindex][1],\
kpitches[kindex][0], kpitches[kindex][1], kpitches[kindex][2],\
kcentroids[kindex][0], kcentroids[kindex][1], kcentroids[kindex][2]
kindex += 1
od
printf "\n\n\n", 1
turnoff
endif
endin
i"analyse" 0 1