Mercurial > hg > constant-q-cpp
changeset 72:642df7b3346f
Support returning a magnitude spectrum (dense) etc
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 20 Mar 2014 16:15:43 +0000 |
parents | 4767faa6726f |
children | be277d1367f4 |
files | yeti/cqt.yeti yeti/cqtkernel.yeti yeti/nbproject/ide-file-targets.xml yeti/nbproject/project.xml yeti/plotfile.yeti yeti/test_frequency.yeti |
diffstat | 6 files changed, 164 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/yeti/cqt.yeti Wed Mar 19 10:30:20 2014 +0000 +++ b/yeti/cqt.yeti Thu Mar 20 16:15:43 2014 +0000 @@ -33,6 +33,7 @@ cqtkernel = load cqtkernel; resample = load may.stream.resample; manipulate = load may.stream.manipulate; +mat = load may.matrix; cm = load may.matrix.complex; framer = load may.stream.framer; cplx = load may.complex; @@ -175,7 +176,36 @@ done { rows, columns }; ); - processOctaveLists octs = + assembleBlockSpectrogram bits = + (// As assembleBlock, but producing a dense magnitude + // spectrogram (rather than a complex output with zeros + // between the cell values in lower octaves). (todo: smoothing) + + //eprintln "assembleBlockSpectrogram: structure of bits is:"; + //eprintln (map length bits); + + rows = octaves * kdata.binsPerOctave; + columns = (pow 2 (octaves - 1)) * kdata.atomsPerFrame; + + mat.generate do row col: + + oct = int (row / binsPerOctave); + binNo = row % kdata.binsPerOctave; + + chunks = pow 2 oct; + colsPerAtom = int (columns / (chunks * kdata.atomsPerFrame)); + atomNo = int (col / colsPerAtom); + + if atomNo < length bits[oct] then + cplx.magnitude bits[oct][atomNo][binNo]; + else + 0 + fi; + + done { rows, columns }; + ); + + processOctaveLists assembler octs = case octs[0] of block::rest: (toAssemble = array @@ -189,7 +219,7 @@ array [] fi done (keys octs)); - assembleBlock toAssemble :. \(processOctaveLists octs)); + assembler toAssemble :. \(processOctaveLists assembler octs)); _: [] esac; @@ -218,7 +248,14 @@ done (reverse (list kdata.binFrequencies)) done [0..octaves-1]) }, - output = processOctaveLists octaveLists + octaves, + output type = + case type of + ComplexCQ (): + Complex (processOctaveLists assembleBlock octaveLists); + Spectrogram (): + Real (processOctaveLists assembleBlockSpectrogram octaveLists); + esac } );
--- a/yeti/cqtkernel.yeti Wed Mar 19 10:30:20 2014 +0000 +++ b/yeti/cqtkernel.yeti Thu Mar 20 16:15:43 2014 +0000 @@ -124,7 +124,7 @@ wx1 = vec.maxindex (complex.magnitudes (cm.getRow 0 kmat)); wx2 = vec.maxindex (complex.magnitudes (cm.getRow (cm.height kmat - 1) kmat)); - subset = cm.columnSlice kmat wx1 (wx2+1); + subset = cm.flipped (cm.columnSlice kmat wx1 (wx2+1)); square = cm.product (cm.conjugateTransposed subset) subset; diag = complex.magnitudes (cm.getDiagonal 0 square);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yeti/nbproject/ide-file-targets.xml Thu Mar 20 16:15:43 2014 +0000 @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project basedir=".." name="cqt-IDE"> + <!-- TODO: edit the following target according to your needs --> + <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#debugj2se) --> + <property name="maydir" value="${basedir}/../../may"/> + <property name="yetidir" value="${basedir}/../../yeti"/> + <property name="jardir" value="${maydir}/ext/jar"/> + <path id="cp"> + <fileset dir="${basedir}"> + <include name="cqt.jar"/> + </fileset> + <fileset dir="${jardir}"> + <include name="*.jar"/> + </fileset> + <fileset dir="${yetidir}"> + <include name="yeti.jar"/> + </fileset> + <fileset dir="${maydir}"> + <include name="may.jar"/> + </fileset> + </path> + <target name="debug-nb"> + <nbjpdastart addressproperty="jpda.address" name="cqt" transport="dt_socket"> + <classpath refid="cp"/> + </nbjpdastart> + <!-- TODO configure the main class for your project here: --> + <java classname="plotfile" fork="true"> + <classpath refid="cp"/> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <arg value="${basedir}/test.wav"/> + </java> + </target> + <target name="-profile-check"> + <startprofiler freeform="true"/> + </target> + <!-- TODO: edit the following target according to your needs --> + <!-- (more info: http://netbeans.org/kb/articles/freeform-config.html#profilej2se) --> + <target depends="-profile-check" if="profiler.configured" name="profile-nb"> + <!-- TODO configure the main class for your project here: --> + <java classname="plotfile" fork="true"> + <classpath refid="cp"/> + <jvmarg line="${agent.jvmargs}"/> + <arg value="${basedir}/test.wav"/> + </java> + </target> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yeti/nbproject/project.xml Thu Mar 20 16:15:43 2014 +0000 @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.ant.freeform</type> + <configuration> + <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1"> + <!-- Do not use Project Properties customizer when editing this file manually. + To prevent the customizer from showing, create nbproject/project.properties file and enter +auxiliary.show.customizer=false +property there. Adding +auxiliary.show.customizer.message=<message> + will show your customized message when someone attempts to open the customizer. --> + <name>cqt</name> + <properties/> + <folders/> + <ide-actions> + <action name="build"> + <target>jar</target> + </action> + <action name="clean"> + <target>clean</target> + </action> + <action name="rebuild"> + <target>clean</target> + <target>jar</target> + </action> + <action name="debug"> + <script>nbproject/ide-file-targets.xml</script> + <target>debug-nb</target> + </action> + <action name="profile"> + <script>nbproject/ide-file-targets.xml</script> + <target>profile-nb</target> + </action> + </ide-actions> + <view> + <items> + <source-file> + <location>build.xml</location> + </source-file> + </items> + <context-menu> + <ide-action name="build"/> + <ide-action name="rebuild"/> + <ide-action name="clean"/> + <ide-action name="debug"/> + <ide-action name="profile"/> + </context-menu> + </view> + <subprojects/> + </general-data> + <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/1"/> + </configuration> +</project>
--- a/yeti/plotfile.yeti Wed Mar 19 10:30:20 2014 +0000 +++ b/yeti/plotfile.yeti Thu Mar 20 16:15:43 2014 +0000 @@ -8,23 +8,34 @@ { cqt } = load cqt; +minFreq = 27.5; +maxRateDivisor = 3; +binsPerOctave = 60; + plotfile f = (testStream = af.open f; eprintln "Opened file stream..."; + start = System#currentTimeMillis(); cq = cqt { - maxFreq = testStream.sampleRate/2, - minFreq = 50, - binsPerOctave = 24 + maxFreq = testStream.sampleRate/maxRateDivisor, + minFreq, + binsPerOctave } testStream; - eprintln "Generated kernel and primed transform, now calculating..."; - bigM = mat.concatHorizontal (map cm.magnitudes cq.output); + middle = System#currentTimeMillis(); + eprintln "Generated kernel \(cm.size cq.kernel.kernel) and primed transform (\(cq.octaves) octaves), took \(middle-start)ms, now calculating..."; + bigM = case (cq.output (Spectrogram ())) of + Real s: mat.concatHorizontal s; + _: failWith "Real expected"; + esac; + finish = System#currentTimeMillis(); + eprintln "Done, that part took \(finish-middle)ms, all CQ stuff took \(finish-start)ms"; eprintln "Plotting..."; \() (plot.plot [Contour bigM])); usage () = (eprintln "\nUsage: plotfile file.wav"; - eprintln "\n Loads audio from file.wav and plots a 24bpo Constant-Q spectrogram"; - eprintln " from 50Hz up to half the file samplerate"); + eprintln "\n Loads audio from file.wav and plots a \(binsPerOctave)bpo Constant-Q spectrogram"; + eprintln " from \(minFreq)Hz up to 1/\(maxRateDivisor) of the file samplerate"); case (list _argv) of file::[]: plotfile file;
--- a/yeti/test_frequency.yeti Wed Mar 19 10:30:20 2014 +0000 +++ b/yeti/test_frequency.yeti Thu Mar 20 16:15:43 2014 +0000 @@ -81,7 +81,11 @@ do f: \( str = streamBuilder f; cq = cqt { maxFreq = cqmax, minFreq = cqmin, binsPerOctave = bpo } str; - m = mat.concatHorizontal (map cm.magnitudes cq.output); + out = case cq.output (ComplexCQ ()) of + Complex c: c; + _: failWith "expected complex"; + esac; + m = mat.concatHorizontal (map cm.magnitudes out); // println "binFrequencies = \(cq.kernel.binFrequencies)"; // println "binForFreq \(f) = \(binForFreq f)"; var colno = 0;