Mercurial > hg > beaglert
changeset 235:3d41a6fa1830
Merge
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sun, 10 Apr 2016 04:08:06 +0200 |
parents | 869f5e703844 (current diff) 99b4d81d9c95 (diff) |
children | cb47043c8c28 |
files | include/Scope.h projects/heavy/pd/hello-midi/hv_ctlin.pd projects/heavy/pd/hello-midi/hv_notein.pd projects/heavy/pd/hello-midi/hv_pgmin.pd |
diffstat | 36 files changed, 3138 insertions(+), 618 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Sat Feb 13 01:51:01 2016 +0000 +++ b/.cproject Sun Apr 10 04:08:06 2016 +0200 @@ -34,8 +34,11 @@ <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/ne10/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> - <option id="gnu.cpp.compiler.option.other.other.1516989263" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -Wpointer-arith -Wunused-result -D_GNU_SOURCE -D_REENTRANT -D__XENO__" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.1516989263" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -Wpointer-arith -Wunused-result -D_GNU_SOURCE -D_REENTRANT -D__XENO__ -fpermissive" valueType="string"/> <option id="gnu.cpp.compiler.option.warnings.allwarn.1392851614" name="All warnings (-Wall)" superClass="gnu.cpp.compiler.option.warnings.allwarn" value="true" valueType="boolean"/> <option id="gnu.cpp.compiler.option.dialect.std.904910934" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1166892316" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> @@ -48,7 +51,10 @@ <listOptionValue builtIn="false" value="/usr/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/ne10/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> <option id="gnu.c.compiler.option.misc.other.835792865" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -Wpointer-arith -Wunused-result -D_GNU_SOURCE -D_REENTRANT -D__XENO__ -std=gnu99" valueType="string"/> <option id="gnu.c.compiler.option.warnings.allwarn.1145989346" name="All warnings (-Wall)" superClass="gnu.c.compiler.option.warnings.allwarn" value="true" valueType="boolean"/> @@ -60,15 +66,19 @@ <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib/xenomai"/> <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/xenomai/lib"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/> <listOptionValue builtIn="false" value="/usr/lib/arm-linux-gnueabihf"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/lib"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/lib"/> </option> <option id="gnu.cpp.link.option.libs.139390951" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"> <listOptionValue builtIn="false" value="rt"/> + <listOptionValue builtIn="false" value="pd"/> <listOptionValue builtIn="false" value="native"/> <listOptionValue builtIn="false" value="xenomai"/> + <listOptionValue builtIn="false" value="sndfile"/> </option> - <option id="gnu.cpp.link.option.flags.2096887116" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -rdynamic" valueType="string"/> + <option id="gnu.cpp.link.option.flags.2096887116" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -rdynamic -Wl,-unresolved-symbols=ignore-in-shared-libs" valueType="string"/> <option id="gnu.cpp.link.option.userobjs.537608578" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs"> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libprussdrv.a}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libNE10.a}""/> @@ -83,6 +93,9 @@ <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/ne10/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1788972942" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> </tool> @@ -123,7 +136,7 @@ <sourceEntries> <entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/audio_in_FFT"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_libpd"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -149,7 +162,7 @@ <folderInfo id="cdt.managedbuild.config.gnu.exe.release.1521194538." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1612059942" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release"> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.908983575" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/> - <builder arguments="-j6" buildPath="${workspace_loc:/BBB_audio+input/Release}" command="make" id="cdt.managedbuild.target.gnu.builder.exe.release.511190290" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/> + <builder buildPath="${workspace_loc:/BBB_audio+input/Release}" enabledIncrementalBuild="true" id="cdt.managedbuild.target.gnu.builder.exe.release.511190290" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="6" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/> <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.archiver.base.810674388" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> <tool command="arm-linux-gnueabihf-gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release"> <option id="gnu.cpp.compiler.exe.release.option.optimization.level.2031085570" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> @@ -161,9 +174,11 @@ <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> <option id="gnu.cpp.compiler.option.dialect.std.776548502" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.other.398422461" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -U_FORTIFY_SOURCE" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.398422461" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -U_FORTIFY_SOURCE -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon --fast-math -ftree-vectorize -ftree-vectorizer-verbose=10" valueType="string"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.601059736" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> </tool> <tool command="arm-linux-gnueabihf-gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release"> @@ -176,28 +191,34 @@ <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/ne10/"/> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> <option id="gnu.c.compiler.option.include.files.40806287" name="Include files (-include)" superClass="gnu.c.compiler.option.include.files"/> <option id="gnu.c.compiler.option.preprocessor.undef.symbol.980935416" name="Undefined symbols (-U)" superClass="gnu.c.compiler.option.preprocessor.undef.symbol" valueType="undefDefinedSymbols"> <listOptionValue builtIn="false" value="_FORTIFY_SOURCE"/> </option> + <option id="gnu.c.compiler.option.misc.other.1568308112" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon --fast-math -ftree-vectorize -ftree-vectorizer-verbose=10" valueType="string"/> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.574072828" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> </tool> <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.c.linker.exe.release.281634187" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/> <tool command="arm-linux-gnueabihf-g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.929570421" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release"> <option id="gnu.cpp.link.option.paths.277042583" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths"> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib/xenomai"/> <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/xenomai/lib"/> <listOptionValue builtIn="false" value="/usr/lib/arm-linux-gnueabihf"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/lib"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/lib"/> </option> <option id="gnu.cpp.link.option.libs.1930118082" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"> <listOptionValue builtIn="false" value="rt"/> + <listOptionValue builtIn="false" value="pd"/> <listOptionValue builtIn="false" value="native"/> <listOptionValue builtIn="false" value="xenomai"/> </option> - <option id="gnu.cpp.link.option.flags.1308374111" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -Wpointer-arith" valueType="string"/> + <option id="gnu.cpp.link.option.flags.1308374111" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -Wpointer-arith -Wl,-unresolved-symbols=ignore-in-shared-libs" valueType="string"/> <option id="gnu.cpp.link.option.userobjs.1473502069" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs"> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libprussdrv.a}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libNE10.a}""/> @@ -210,6 +231,9 @@ <tool command="arm-linux-gnueabihf-as" id="cdt.managedbuild.tool.gnu.assembler.exe.release.2052985276" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release"> <option id="gnu.both.asm.option.include.paths.1499955275" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/ne10/"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/"/> </option> <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1212659593" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> </tool> @@ -240,7 +264,7 @@ <sourceEntries> <entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/audio_in_FFT"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_libpd"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -252,23 +276,23 @@ <project id="BBB_audio+input.cdt.managedbuild.target.gnu.exe.1596461844" name="Executable" projectType="cdt.managedbuild.target.gnu.exe"/> </storageModule> <storageModule moduleId="refreshScope" versionNumber="2"> - <configuration configurationName="Release"> - <resource resourceType="PROJECT" workspacePath="/BBB_SimpleInstrument"/> - </configuration> <configuration configurationName="basic"> <resource resourceType="PROJECT" workspacePath="/BeagleRT"/> </configuration> <configuration configurationName="Debug"> <resource resourceType="PROJECT" workspacePath="/BBB_SimpleInstrument"/> </configuration> + <configuration configurationName="Release"> + <resource resourceType="PROJECT" workspacePath="/BBB_SimpleInstrument"/> + </configuration> </storageModule> <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> <storageModule moduleId="scannerConfiguration"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> - <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048;cdt.managedbuild.tool.gnu.cpp.compiler.input.601059736"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/> + <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968;cdt.managedbuild.tool.gnu.c.compiler.input.574072828"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> </scannerConfigBuildInfo> <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.528876549;cdt.managedbuild.config.gnu.exe.debug.528876549.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.2030825480;cdt.managedbuild.tool.gnu.cpp.compiler.input.1166892316"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/> @@ -276,8 +300,8 @@ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.528876549;cdt.managedbuild.config.gnu.exe.debug.528876549.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.917207395;cdt.managedbuild.tool.gnu.c.compiler.input.308014221"> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968;cdt.managedbuild.tool.gnu.c.compiler.input.574072828"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/> + <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.1521194538;cdt.managedbuild.config.gnu.exe.release.1521194538.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048;cdt.managedbuild.tool.gnu.cpp.compiler.input.601059736"> + <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/> </scannerConfigBuildInfo> </storageModule> </cproject>
--- a/Makefile Sat Feb 13 01:51:01 2016 +0000 +++ b/Makefile Sun Apr 10 04:08:06 2016 +0200 @@ -8,7 +8,7 @@ RM := rm -rf STATIC_LIBS := ./libprussdrv.a ./libNE10.a -LIBS := -lrt -lnative -lxenomai -lsndfile +LIBS := -lrt -lnative -lxenomai -lsndfile -lpd INCLUDES := -I./include -I/usr/include/ne10 -I/usr/xenomai/include -I/usr/arm-linux-gnueabihf/include/xenomai/include -I/usr/arm-linux-gnueabihf/include/ne10 @@ -36,8 +36,8 @@ DEFAULT_MAIN_OBJS := ./build/core/default_main.o DEFAULT_MAIN_CPP_DEPS := ./build/core/default_main.d -CPP_FLAGS=-O2 -C_FLAGS=-O2 +CPP_FLAGS=-O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon --fast-math -ftree-vectorize +C_FLAGS=-O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon --fast-math -ftree-vectorize # all = build BeagleRT all: SYNTAX_FLAG :=
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/IirFilter.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,69 @@ +/* + * IirFilter.cpp + * + * Created on: 17 Sep 2015 + * Author: giulio + */ +#include "IirFilter.h" + +IirFilterStage::IirFilterStage(){ + for(int n = 0; n < IIR_FILTER_STAGE_COEFFICIENTS; n++){ + coefficients[n] = 0; + } + for(int n = 0; n < IIR_FILTER_STAGE_STATES; n++){ + states[n]=0; + } +} +void IirFilterStage::setCoefficients(double* newCoefficients){ + for(int n = 0; n < IIR_FILTER_STAGE_COEFFICIENTS; n++){ + coefficients[n] = newCoefficients[n]; + } +} +void IirFilterStage::setStates(double* newStates){ + for(int n = 0; n < IIR_FILTER_STAGE_STATES; n++){ + states[n] = newStates[n]; + } +} + +/* struct IirFilterStage* stages; + int numberOfStages; +*/ +IirFilter::IirFilter(){ + stages=(IirFilterStage**)0; + setNumberOfStages(0); +} +IirFilter::IirFilter(int newNumberOfStages){ + setNumberOfStages(newNumberOfStages); +} +IirFilter::IirFilter(int newNumberOfStages, double* newCoefficients){ + setNumberOfStages(newNumberOfStages); + setCoefficients(newCoefficients); +} +void IirFilter::dealloc(){ + if( stages == 0 ) + return; + for(int n = 0; n < numberOfStages; n++){ + delete stages[n]; + } + delete stages; + stages = 0; + numberOfStages = 0; +} +void IirFilter::setCoefficients(double* newCoefficients){ + for(int n = 0; n < numberOfStages; n++){ + stages[n]->setCoefficients(newCoefficients); + } +}; +void IirFilter::setStates(double* newStates){ + for(int n = 0; n < numberOfStages; n++){ + stages[n]->setStates(newStates); + } +}; +void IirFilter::setNumberOfStages(int newNumberOfStages){ + dealloc(); + numberOfStages=newNumberOfStages; + stages = new IirFilterStage*[numberOfStages]; + for( int n = 0; n < numberOfStages; n++){ + stages[n] = new IirFilterStage; + } +}
--- a/core/Midi.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/core/Midi.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -58,6 +58,11 @@ messages[writePointer].setDataByte(elapsedDataBytes, input[n]); elapsedDataBytes++; if(elapsedDataBytes == messages[writePointer].getNumDataBytes()){ + // done with the current message + // call the callback if available + if(isCallbackEnabled() == true){ + messageReadyCallback(getNextChannelMessage(), callbackArg); + } waitingForStatus = true; writePointer++; if(writePointer == messages.size()){ @@ -66,6 +71,7 @@ } } } + return consumedBytes; }; @@ -104,14 +110,12 @@ } void Midi::midiInputLoop(){ - printf("Midi input loop %d\n", objAddrs[kMidiInput].size()); for(unsigned int n = 0; n < objAddrs[kMidiInput].size(); n++){ objAddrs[kMidiInput][n] -> readInputLoop(); } } void Midi::midiOutputLoop(){ - printf("Midi output loop %d\n", objAddrs[kMidiOutput].size()); for(unsigned int n = 0; n < objAddrs[kMidiOutput].size(); n++){ objAddrs[kMidiOutput][n] -> writeOutputLoop(); } @@ -132,6 +136,7 @@ if(inputBytesWritePointer == inputBytes.size()){ //wrap pointer around inputBytesWritePointer = 0; } + if(parserEnabled == true && ret > 0){ // if the parser is enabled and there is new data, send the data to it int input; while((input=_getInput()) >= 0){ @@ -168,10 +173,9 @@ objAddrs[kMidiInput].push_back(this); inputPort = open("/dev/midi1", O_RDONLY | O_NONBLOCK | O_NOCTTY); if(inputPort < 0){ - printf("Error occurred while opening midi input port %d: %d", port, inputPort); return -1; } else { - printf("Reading from port %d\n", port); + printf("Reading from Midi port %d\n", port); BeagleRT_scheduleAuxiliaryTask(midiInputTask); return 1; } @@ -181,7 +185,6 @@ objAddrs[kMidiOutput].push_back(this); outputPort = open("/dev/midi1", O_WRONLY, 0); if(outputPort < 0){ - printf("Error occurred while opening midi output port %d: %d", port, outputPort); return -1; } else { printf("Writing to Midi port %d\n", port);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/NetworkSend.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,257 @@ +#include "NetworkSend.h" + +#ifdef USE_JUCE +#else +//initialize the static members of NetworkSend +bool NetworkSend::staticConstructed=false; +int NetworkSend::sleepTimeMs; +bool NetworkSend::threadIsExiting; +bool NetworkSend::threadRunning; +std::vector<NetworkSend*> NetworkSend::objAddrs(0); +AuxiliaryTask NetworkSend::sendDataTask=NULL; + +void sendData(){ + NetworkSend::run(); +} +void NetworkSend::staticConstructor(){ + if(staticConstructed==true) + return; + staticConstructed=true; + threadIsExiting=false; + threadRunning=false; + sendDataTask = BeagleRT_createAuxiliaryTask(::sendData, 95, "sendDataTask"); //TODO: allow variable priority +} +void NetworkSend::sendAllData(){ + for(unsigned int n=0; n<NetworkSend::objAddrs.size(); n++){ + NetworkSend::objAddrs[n]->sendData(); + } +} +int NetworkSend::getNumInstances(){ + return objAddrs.size(); +} +void NetworkSend::startThread(){ + BeagleRT_scheduleAuxiliaryTask(sendDataTask); +} +void NetworkSend::stopThread(){ + threadIsExiting=true; +} +bool NetworkSend::threadShouldExit(){ + return(gShouldStop || threadIsExiting); +} +bool NetworkSend::isThreadRunning(){ + return threadRunning; +} +#endif /* USE_JUCE */ + +#ifdef USE_JUCE +NetworkSend::NetworkSend(const String &threadName): + Thread(threadName) +#else +NetworkSend::NetworkSend() +#endif /* USE_JUCE */ +{ + channel.buffers=NULL; + channel.doneOnTime=NULL; + channel.readyToBeSent=NULL; + channel.enabled=false; + sleepTimeMs=2; //This should actually be initialized in the staticConstructor for non-Juce code, but doing it here makes it more portable + channel.sampleCount=0; +} + +NetworkSend::~NetworkSend(){ +#ifdef USE_JUCE + stopThread(1000); +#else + stopThread(); + for(unsigned int n=0; n<objAddrs.size(); n++){ //keep track of deleted instances; + if(objAddrs[n]==this){ + objAddrs.erase(objAddrs.begin()+n); + break; + } + } +#endif + dealloc(); +} +void NetworkSend::dealloc(){ + channel.enabled=false; + if(channel.buffers!=NULL){ + for(int n=0; n<channel.numBuffers; n++){ + free(channel.buffers[n]); + channel.buffers[n]=NULL; + } + free(channel.buffers); + channel.buffers=NULL; + } + free(channel.readyToBeSent); + channel.readyToBeSent=NULL; + free(channel.doneOnTime); + channel.doneOnTime=NULL; +} +void NetworkSend::cleanup(){ + dealloc(); +} + +void NetworkSend::setup(float aSampleRate, int blockSize, int aChannelNumber, int aPort, const char *aServer){ +#ifdef USE_JUCE +#else + staticConstructor(); //FIXME: ideally this should be in the constructor, but this is not currently possible + //because of limitations in BeagleRT_createAuxiliaryTask() + //keep track of added active instances + objAddrs.push_back(this);//TODO: this line should be in the constructor, but something weird happens if + // an instance of NetworkSend is then declared globally: the constructor gets called, + // and objAddrs.size()==1 but when you get to setup, objAddrs.size() has reverted back to 0, without + // any destructor being called in between ... Have a look here + // http://stackoverflow.com/questions/7542054/global-vector-emptying-itself-between-calls . + // and maybe use accessor function instead of global, as was done in #1374 +#endif /* USE_JUCE */ + cleanup(); + int numSamples=blockSize*4>4*channel.bufferLength ? blockSize*4 : 4*channel.bufferLength; + channel.numBuffers= (1+numSamples/channel.bufferLength) * 3; //the +1 takes the ceil() of the division + channel.buffers=(float**)malloc(channel.numBuffers*sizeof(float*)); + printf("NumBuffers: %d\n", channel.numBuffers); + if(channel.buffers==NULL) + return; + for(int n=0; n<channel.numBuffers; n++){ + channel.buffers[n]=(float*)malloc(channel.bufferLength*sizeof(float)); + if(channel.buffers[n]==NULL) + return; + } + channel.readyToBeSent=(bool*)malloc(channel.numBuffers*sizeof(bool)); + channel.doneOnTime=(bool*)malloc(channel.numBuffers*sizeof(bool)); + for(int n=0; n<channel.numBuffers; n++){ + channel.readyToBeSent[n]=false; + channel.doneOnTime[n]=true; + } + if(channel.readyToBeSent==NULL || channel.doneOnTime==NULL) + return; + channel.writePointer=channel.headerLength; + channel.writeBuffer=0; + channel.readBuffer=0; + setChannelNumber(aChannelNumber); + setPort(aPort); //TODO: check for the return value + setServer(aServer); //TODO: check for the return value + printf("Channel %d is sending messages to: %s:%d at %fHz\n", getChannelNumber(), aServer, aPort, aSampleRate); + channel.enabled=true; +} + +void NetworkSend::log(float value){ //TODO: add a vectorized version of this method + if(channel.enabled==false) + return; + if(channel.writePointer==channel.bufferLength){ // when the buffer is filled ... + channel.readyToBeSent[channel.writeBuffer]=true; // flag it as such +// printf("Scheduling for send %d\n",(int)channel.buffers[channel.writeBuffer][channel.headerTimestampIndex]); + channel.writePointer=channel.headerLength; //reset the writePointer + channel.writeBuffer=(channel.writeBuffer+1); //switch buffer + if(channel.writeBuffer==channel.numBuffers) // and wrap it + channel.writeBuffer=0; +// printf("WriteBuffer:%d\n", channel.writeBuffer); + if(channel.doneOnTime[channel.writeBuffer]==false){ //check if this buffer's last sending has completed on time ... + printf("NetworkSend buffer underrun. timestamp: %d :-{\n", + (int)channel.buffers[channel.writeBuffer][channel.headerTimestampIndex]); + } + channel.doneOnTime[channel.writeBuffer]=false; // ... and then reset the flag +#ifdef USE_JUCE + if(isThreadRunning()==false){ + startThread(10); + } +#else + if(isThreadRunning()==false){ + startThread(); + } +#endif /* USE_JUCE */ + } + if(channel.writePointer==channel.headerLength){ // we are about to start writing in the buffer, let's set the header + //set dynamic header values here. Static values are set in setup() and setChannelNumber(). + channel.buffers[channel.writeBuffer][channel.headerTimestampIndex]=(float)channel.sampleCount; //timestamp + channel.sampleCount++; + //add here more header fields + } + channel.buffers[channel.writeBuffer][channel.writePointer++]=value; +// sampleCount++; +}; + +void NetworkSend::setServer(const char *aServer){ +#ifdef USE_JUCE + remoteHostname=String::fromUTF8(aServer); +#else + udpClient.setServer(aServer); +#endif /* USE_JUCE */ +} +void NetworkSend::setPort(int aPort){ +#ifdef USE_JUCE + remotePortNumber=aPort; +#else + udpClient.setPort(aPort); +#endif /* USE_JUCE */ +} + +void NetworkSend::setChannelNumber(int aChannelNumber){ + channel.channelNumber=aChannelNumber; + for(int n=0; n < channel.numBuffers; n++){ //initialize the header + channel.buffers[n][channel.headerChannelIndex]=channel.channelNumber; + //add here more static header fields + } +}; +int NetworkSend::getChannelNumber(){ + return channel.channelNumber; +}; + +int NetworkSend::getTimestamp(){ + return channel.buffers[channel.readBuffer][channel.headerTimestampIndex]; +} + +void NetworkSend::sendData(){ + if(channel.enabled==false) + return; + while(channel.readyToBeSent[channel.readBuffer]==true){ + channel.readyToBeSent[channel.readBuffer]=false; + void* sourceBuffer=channel.buffers[channel.readBuffer]; +// printf("Trying to send timestamp %d\n",(int)((float*)sourceBuffer)[channel.headerTimestampIndex]); +// printf("ReadBuffer:%d\n", channel.readBuffer); + unsigned int numBytesToSend=NETWORK_AUDIO_BUFFER_SIZE*sizeof(float); + //TODO: call waitUntilReady before trying to write/send, to avoid blocks! (OR NOT?) +#ifdef USE_JUCE + if(1==udpClient.waitUntilReady(0, 5)){ + udpClient.write(remoteHostname, remotePortNumber, sourceBuffer, numBytesToSend); + channel.doneOnTime[channel.readBuffer]=true; + // printf ("Sent timestamp: %d\n", (int)((float*)sourceBuffer)[1]); + } else { + // printf ("Not ready timestamp: %d\n", (int)((float*)sourceBuffer)[1]); + } +#else + udpClient.send(sourceBuffer, numBytesToSend); +// printf("sent sourceBuffer: %d, channel: %f, timestamp: %f\n", channel.readBuffer, channel.buffers[channel.readBuffer][0], +// channel.buffers[channel.readBuffer][1]); + channel.doneOnTime[channel.readBuffer]=true; +#endif /* USE_JUCE */ + channel.readBuffer++; + if(channel.readBuffer==channel.numBuffers) + channel.readBuffer=0; + } +} + +void NetworkSend::run(){ +#ifdef USE_JUCE + // std::chrono::high_resolution_clock::time_point t1; + // std::chrono::high_resolution_clock::time_point t2; + // std::chrono::high_resolution_clock::time_point t3; + while(threadShouldExit()==false){ + // t3 = std::chrono::high_resolution_clock::now(); + // t1 = std::chrono::high_resolution_clock::now(); + sendData(); + // t2 = std::chrono::high_resolution_clock::now(); + // auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>( t3 - t1 ).count(); + // auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count(); + // if(duration2>0) + // std::cout << "Duration is: " << duration2 <<". Whole loop is: " << duration1 << "\n"; + usleep(1000); + } +#else + threadRunning=true; + while(threadShouldExit()==false){ + sendAllData(); + usleep(sleepTimeMs*1000); + } + threadRunning=false; +#endif +}
--- a/core/PRU.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/core/PRU.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -99,7 +99,7 @@ const unsigned int PRU::kPruGPIOTestPin2 = 31; // GPIO0(31); P9-13 const unsigned int PRU::kPruGPIOTestPin3 = 26; // GPIO0(26); P8-14 -extern bool gShouldStop; +extern int gShouldStop; extern int gRTAudioVerbose; // Constructor: specify a PRU number (0 or 1) @@ -561,12 +561,12 @@ // Convert short (16-bit) samples to float // TODO: NEON for(unsigned int n = 0; n < 2 * context->audioFrames; n++) - context->audioIn[n] = (float)pru_buffer_audio_adc[n + pru_audio_offset] / 32768.0; + context->audioIn[n] = (float)pru_buffer_audio_adc[n + pru_audio_offset] / 32768.0f; if(analog_enabled) { // TODO: NEON for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) - context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0; + context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0f; if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { // Initialize the output buffer with the values that were in the last frame of the previous output @@ -614,7 +614,7 @@ // Convert float back to short for SPI output for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { - int out = context->analogOut[n] * 65536.0; + int out = context->analogOut[n] * 65536.0f; if(out < 0) out = 0; else if(out > 65535) out = 65535; pru_buffer_spi_dac[n + pru_spi_offset] = (uint16_t)out; @@ -630,7 +630,7 @@ // Convert float back to short for audio // TODO: NEON for(unsigned int n = 0; n < 2 * context->audioFrames; n++) { - int out = context->audioOut[n] * 32768.0; + int out = context->audioOut[n] * 32768.0f; if(out < -32768) out = -32768; else if(out > 32767) out = 32767; pru_buffer_audio_dac[n + pru_audio_offset] = (int16_t)out;
--- a/core/RTAudio.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/core/RTAudio.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -64,7 +64,7 @@ } // Flag which tells the audio task to stop -bool gShouldStop = false; +int gShouldStop = false; // general settings char gPRUFilename[MAX_PRU_FILENAME_LENGTH]; // Path to PRU binary file (internal code if empty)_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/ReceiveAudioThread.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,313 @@ +#include "ReceiveAudioThread.h" + +#ifdef USE_JUCE +#else +//initialise static members +bool ReceiveAudioThread::staticConstructed=false; +AuxiliaryTask ReceiveAudioThread::receiveDataTask=NULL; +std::vector<ReceiveAudioThread *> ReceiveAudioThread::objAddrs(0); +bool ReceiveAudioThread::threadRunning; +bool ReceiveAudioThread::threadIsExiting; +int ReceiveAudioThread::sleepTime; + +void receiveData(){ + ReceiveAudioThread::run(); +} +void ReceiveAudioThread::staticConstructor(){ + if(staticConstructed==true) + return; + staticConstructed=true; + threadIsExiting=false; + receiveDataTask=BeagleRT_createAuxiliaryTask(receiveData, 90, "receiveDataTask"); //TODO: allow different priorities +} +#endif /* USE_JUCE */ + +void ReceiveAudioThread::dealloc(){ + free(buffer); + buffer=NULL; + free(stackBuffer); + stackBuffer=NULL; +} +void ReceiveAudioThread::wrapWritePointer(){ + //this is not quite a simple wrapping as you would do in a circular buffer, + //as there is no guarantee the buffer will be full at all times, given that there must alwas be enough space at the end of it + //to hold a full payload + // lastValidPointer indicates the last pointer in the buffer containing valid data + // + if(writePointer+payloadLength+headerLength>bufferLength){ //if we are going to exceed the length of the buffer with the next reading + // lastValidPointer=writePointer+headerLength; //remember where the last valid data are + // for(int n=headerLength;n<lastValidPointer; n++){ + // fprintf(fd2, "%f\n",buffer[n]); //DEBUG + // } + writePointer=0; //and reset to beginning of the buffer + } +} +void ReceiveAudioThread::pushPayload(int startIndex){ //backup the payload samples that will be overwritten by the new header + for(int n=0; n<headerLength; n++){ + stackBuffer[n]=buffer[startIndex+n]; + } +} +void ReceiveAudioThread::popPayload(int startIndex){ + for(int n=0; n<headerLength; n++){ + buffer[startIndex+n]=stackBuffer[n]; + } +} + +int ReceiveAudioThread::readUdpToBuffer(){ + + if(listening==false || bufferReady==false) + return 0; + if(writePointer<0) + return 0; + if(socket.waitUntilReady(true, waitForSocketTime)){// TODO: if waitForSocketTime here is >>5, the + // destructor (always or sometimes) never actually gets called, despite run() returns ...see issue #1381 +#ifdef USE_JUCE +#else + lastTime=rt_timer_read(); +// rt_printf("lastTimeread= %llu\n", lastTime); +#endif /* USE_JUCE */ + pushPayload(writePointer); //backup headerLength samples. This could be skipped if writePointer==0 + //read header+payload + int numBytes=socket.read(buffer+writePointer, bytesToRead, true); //read without waiting. + //TODO: (if using variable-length payload) validate the actual numBytes read against the size declared in the header + if(numBytes<0){ + printf("error numBytes1\n"); + return -3; //TODO: something went wrong, you have to discard the rest of the packet! + } + if(numBytes==0){//TODO: this should not happen unless you actually receive a packet of size zero (is it at all possible?) +// printf("received 0 bytes\n"); + return 0; + } + if(numBytes != bytesToRead){ //this is equivalent to (numBytes<bytesToRead) + printf("error numBytes2: %d\n", numBytes); + return -4; //TODO: something went wrong, less bytes than expected in the payload. + } + if(channel!=(int)buffer[writePointer]){ +// printf("I am channel %d, but I received data for channel %d\n", channel, (int)buffer[writePointer]); + return -5; + } + if(buffer[writePointer+1]!=timestamp+1) + printf("missing a timestamp: %d\n",timestamp+1); + timestamp=buffer[writePointer+1]; +// rt_printf("Received a message of length %d, it was on channel %d and timestamp %d\n", numBytes, (int)buffer[writePointer], (int)buffer[writePointer+1]); + + popPayload(writePointer); //restore headerLength payload samples. This could be skipped if writePointer==0 + //even though we just wrote (payloadLength+headerLength) samples in the buffer, + //we only increment by payloadLength. This way, next time a socket.read is performed, we will + //backup the last headerLength samples that we just wrote and we will overwrite them with + //the header from the new read. After parsing the header we will then restore the backed up samples. + //This way we guarantee that, apart from the first headerLength samples, buffer is a circular buffer! + writePointer+=payloadLength; + wrapWritePointer(); + return numBytes; + } + return 0; //timeout occurred +} +//USE_JUCE Thread(threadName), +#ifdef USE_JUCE +ReceiveAudioThread::ReceiveAudioThread(const String &threadName) : + Thread(threadName), +#else +ReceiveAudioThread::ReceiveAudioThread() : +#endif /* USE_JUCE */ + socket(0), + listening(false), + bufferReady(false), + buffer(NULL), + stackBuffer(NULL), + bufferLength(0), + lastValidPointer(0), + waitForSocketTime(5), +#ifdef USE_JUCE + threadPriority(5) +#else + threadPriority(88) +#endif /* USE_JUCE */ +{}; +ReceiveAudioThread::~ReceiveAudioThread(){ +#ifdef USE_JUCE + stopThread(1000); +#else + stopThread(); + while(threadRunning){ + usleep(sleepTime*2); //wait for thread to stop + std::cout<< "Waiting for receiveAudioTask to stop" << std::endl; + } +#endif /* USE_JUCE */ + //TODO: check if thread stopped, otherwise kill it before dealloc + dealloc(); +} +void ReceiveAudioThread::init(int aPort, int aSamplesPerBlock, int aChannel){ + dealloc(); +#ifdef USE_JUCE +#else + staticConstructor(); + objAddrs.push_back(this);//TODO: this line should be in the constructor +#endif /* USE_JUCE */ + bindToPort(aPort); + channel=aChannel; + printf("Channel %d is receiving on port %d\n",aChannel, aPort); + // fd=fopen("output.m","w"); //DEBUG + // fprintf(fd,"var=["); //DEBUG + headerLength=2; + payloadLength=300; //TODO: make sure that payloadLength and headerLength are the same as the client is sending. + bufferLength=10 * std::max(headerLength+(payloadLength*4), headerLength+(aSamplesPerBlock*4)); //there are many considerations that can be done here ... + //We keep a headerLength padding at the beginning of the array to allow full reads from the socket + buffer=(float*)malloc(sizeof(float)*bufferLength); + if(buffer==NULL) // something wrong + return; + lastValidPointer=headerLength+ ((bufferLength-headerLength)/payloadLength)*payloadLength; + memset(buffer,0,bufferLength*sizeof(float)); + stackBuffer=(float*)malloc(sizeof(float)*headerLength); + if(stackBuffer==NULL) // something wrong + return; + bufferReady=true; + bytesToRead=sizeof(float)*(payloadLength + headerLength); + writePointer=-1; + readPointer=0; + sleepTime=payloadLength/(float)44100 /4.0; //set sleepTime so that you do not check too often or too infrequently + timestamp=0; +#ifdef USE_JUCE + startThread(threadPriority); +#else + //TODO: the thread cannot be started here at the moment because init() is called in setup(), where tasks cannot be scheduled +#endif /* USE_JUCE */ +} + +void ReceiveAudioThread::bindToPort(int aPort){ + listening=socket.bindToPort(aPort); +#ifdef USE_JUCE +#else + if(listening==false) //this condition is valid also for USE_JUCE, but we do not printf in USE_JUCE + printf("Could not bind to port %d\n",aPort); +#endif /* USE_JUCE */ +} +bool ReceiveAudioThread::isListening(){ + return listening; +} +float* ReceiveAudioThread::getCurrentBuffer(int length){ // NOTE: this cannot work all the time unless samplesPerBuffer and payloadLength are multiples + //TODO: make it return the number of samples actually available at the specified location + if(isListening()==false || length>bufferLength) + return NULL; + readPointer+=length; + if(readPointer>lastValidPointer){ + readPointer=headerLength; + } + return buffer+(int)readPointer; +}; +int ReceiveAudioThread::getSamplesSrc(float *destination, int length, + float samplingRateRatio, int numChannelsInDestination, + int channelToWriteTo) +{ + if (!(samplingRateRatio>0 && samplingRateRatio<=2)) + return -2; + if(isListening()==false) + return -1; + static int numCalls=0; + if(writePointer<0 /*|| (numCalls&16383)==0*/){ //if writePointer has not been initalized yet ... +#ifdef USE_JUCE +#else //debug + readPointer = headerLength; +#endif /* USE_JUCE */ + // this cumbersome line means: start writing at a position which is as close as possible + // to the center of the buffer, but still is aligned to (payloadLength*x)+headerLength + // thus allowing buffering to allow clock drift to go either way + writePointer = headerLength + ((bufferLength-headerLength)/payloadLength/2)*payloadLength; + // This will help keeping them in sync. + //TODO: handle what happens when the remote stream is interrupted and then restarted + printf("write pointer inited at: %d\n", writePointer); + } + numCalls++; + if(length>lastValidPointer) { + //not enough samples available, we fill the buffer with what is available, but the destination buffer will not be filled completely + //at this very moment the other thread might be writing at most one payload into the buffer. + //To avoid a race condition, we need to let alone the buffer where we are currently writing + //as writing the payload also temporarily overwrites the previous headerLength samples, we need to account for them as well + //TODO: This assumes that the writePointer and readPointer do not drift. When doing clock synchronization we will find out that it is not true! + length=lastValidPointer-payloadLength-headerLength; + if(length<0) //no samples available at all! + return 0; + } + for(int n=0; n<length; n++){ + destination[n*numChannelsInDestination+channelToWriteTo]=buffer[(int)(0.5+readPointer)];//simple ZOH non-interpolation (nearest neighbour) + // fprintf(fd,"%f, %d, %f;\n",readPointer,writePointer,destination[n]); //DEBUG + readPointer+=samplingRateRatio; + if((int)(0.5+readPointer)>=lastValidPointer){ + readPointer=readPointer-lastValidPointer+headerLength; + } + } + return length; +} +int ReceiveAudioThread::getSamplesSrc(float *destination, int length, float samplingRateRatio){ + return getSamplesSrc(destination, length, samplingRateRatio, 1,0); + // TODO: rewriting this so that it does not call the override method we can save a multiply and add + // for each sample. +} +bool ReceiveAudioThread::isBufferReady(){ + return bufferReady; +} +#ifdef USE_JUCE +#else +void ReceiveAudioThread::startThread(){ + BeagleRT_scheduleAuxiliaryTask(receiveDataTask); +} +void ReceiveAudioThread::stopThread(){ + threadIsExiting=true; +} +bool ReceiveAudioThread::threadShouldExit(){ + return(gShouldStop || threadIsExiting ); +} +RTIME ReceiveAudioThread::getLastTime(){ + return lastTime; +} +#endif /* USE_JUCE */ +int ReceiveAudioThread::getTimestamp(){ + return timestamp; +} +void ReceiveAudioThread::run(){ + // fd2=fopen("buffer.m","w"); //DEBUG + // fprintf(fd2, "buf=["); //DEBUG + threadRunning=true; + int maxCount=10; + int count=0; + // Clean the socket from anything that is currently in it. +#ifdef USE_JUCE + // this is borrowed from BeagleRT's UdpServer class. + int n; + do { + float waste; + if(socket.waitUntilReady(true, 0)==0) + break; + n=socket.read((void*)&waste, sizeof(float), false); + count++; + if(n<0){ + printf("error\n"); + break; + } + printf("n: %d\n",n); + } while (n>0 && (maxCount<=0 || count<maxCount)); +#else + for(unsigned int n=0; n<objAddrs.size(); n++){ + count=objAddrs[n]->socket.empty(maxCount); + } +#endif /* USE_JUCE */ + printf("socket emptied with %d reads\n", count); + + while(!threadShouldExit()){ //TODO: check that the socket buffer is empty before starting +#ifdef USE_JUCE + readUdpToBuffer(); // read into the oldBuffer + sleep(sleepTime); +#else + for(unsigned int n=0; n<ReceiveAudioThread::objAddrs.size(); n++){ + ReceiveAudioThread::objAddrs[n]->readUdpToBuffer(); + } + usleep(sleepTime); //TODO: use rt_task_sleep instead +#endif /* USE_JUCE */ + } + threadRunning=false; + printf("Thread is not running \n"); + // fprintf(fd,"];readPointer,writePointer,lastValidPointer,destination]=deal(var(:,1), var(:,2), var(:,3), var(:,4));"); //DEBUG + // fclose(fd);//DEBUG + // fprintf(fd2,"];");//DEBUG + // fclose(fd2); //DEBUG +}
--- a/core/UdpClient.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/core/UdpClient.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -1,57 +1,77 @@ -/* - * udpClient.cpp - * - * Created on: 19 May 2015 - * Author: giulio moro - */ -#include "../include/UdpClient.h" - - UdpClient::UdpClient(){ - outSocket=socket(AF_INET, SOCK_DGRAM, 0); - isSetPort=false; - isSetServer=false; - enabled=false; - } - UdpClient::UdpClient(int aPort, const char* aServerName){ - outSocket=socket(AF_INET, SOCK_DGRAM, 0); - if(outSocket<0){ - enabled=false; - return; - } - setPort(aPort); - setServer(aServerName); - isSetPort=true; - isSetServer=true; - enabled=true; - } - UdpClient::~UdpClient(){ - close(outSocket); - } - void UdpClient::setPort(int aPort){ - port=aPort; - destinationServer.sin_port = htons(port); - destinationServer.sin_family = AF_INET; - isSetPort=true; - if(isSetServer){ - enabled=true; - } - }; - void UdpClient::setServer(const char* aServerName){ - inet_pton(AF_INET,aServerName,&destinationServer.sin_addr); - isSetServer=true; - if(isSetPort){ - enabled=true; - } - }; - int UdpClient::send(void * message, int size){ - if(!enabled) - return -1; - unsigned int length; - length=sizeof(struct sockaddr_in); - int n=sendto(outSocket,message,size,0,(const struct sockaddr *)&destinationServer,length); - if (n < 0){ - return n; - } - return 1; - }; - +/* + * udpClient.cpp + * + * Created on: 19 May 2015 + * Author: giulio moro + */ +#include "UdpClient.h" + + UdpClient::UdpClient(){ + outSocket=socket(AF_INET, SOCK_DGRAM, 0); + isSetPort=false; + isSetServer=false; + enabled=false; + } + UdpClient::UdpClient(int aPort, const char* aServerName){ + outSocket=socket(AF_INET, SOCK_DGRAM, 0); + if(outSocket<0){ + enabled=false; + return; + } + setPort(aPort); + setServer(aServerName); + isSetPort=true; + isSetServer=true; + enabled=true; + memset(&stTimeOut, 0, sizeof(struct timeval)); + } + UdpClient::~UdpClient(){ + close(outSocket); + } + void UdpClient::setPort(int aPort){ + port=aPort; + destinationServer.sin_port = htons(port); + destinationServer.sin_family = AF_INET; + isSetPort=true; + if(isSetServer){ + enabled=true; + } + }; + void UdpClient::setServer(const char* aServerName){ + inet_pton(AF_INET,aServerName,&destinationServer.sin_addr); + isSetServer=true; + if(isSetPort){ + enabled=true; + } + }; + int UdpClient::send(void * message, int size){ + if(!enabled) + return -1; + unsigned int length; + length=sizeof(struct sockaddr_in); + int n=sendto(outSocket,message,size,0,(const struct sockaddr *)&destinationServer,length); + if (n < 0){ + return n; + } + return 1; + }; + int UdpClient::write(const char* remoteHostname, int remotePortNumber, void* sourceBuffer, int numBytesToWrite){ + setServer(remoteHostname); + setPort(remotePortNumber); + send(sourceBuffer, numBytesToWrite); + } + int UdpClient::waitUntilReady(bool readyForReading, int timeoutMsecs){ +// If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + if(enabled==false) + return -1; + if(timeoutMsecs<0) + return select(outSocket+1, NULL, &stWriteFDS, NULL, NULL); //calling this with a NULL timeout will block indefinitely + FD_ZERO(&stWriteFDS); + FD_SET(outSocket, &stWriteFDS); + float timeOutSecs=timeoutMsecs*0.001; + stTimeOut.tv_sec=(int)timeOutSecs; + timeOutSecs-=(int)timeOutSecs; + stTimeOut.tv_usec=(int)(timeOutSecs*1000000); + int descriptorReady= select(outSocket+1, NULL, &stWriteFDS, NULL, &stTimeOut); + return descriptorReady>0? 1 : descriptorReady; + } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/UdpServer.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,119 @@ +/* + * udpServer.cpp + * + * Created on: 19 May 2015 + * Author: giulio moro + */ +#include "UdpServer.h" + +UdpServer::UdpServer(int aPort){ + init(aPort); +}; +UdpServer::UdpServer(){ + init(0); +} +UdpServer::~UdpServer(){ + close(); +}; +bool UdpServer::init(int aPort){ + enabled=true; + stZeroTimeOut.tv_sec = 0; //set timeout to 0 + stZeroTimeOut.tv_usec = 0; + inSocket=socket(AF_INET, SOCK_DGRAM, 0); + if (inSocket < 0){ + enabled=false; + } + length = sizeof(server); + server.sin_family=AF_INET; + server.sin_addr.s_addr=INADDR_ANY; + enabled=bindToPort(aPort); + wasteBufferSize=2048; + wasteBuffer=malloc(wasteBufferSize); + memset(&stTimeOut,0,sizeof(struct timeval)); + return enabled; +} + +bool UdpServer::bindToPort(int aPort){ + port=aPort; + if(port<1){ + enabled=false; + return false; + } + server.sin_port=htons(port); + if (bind(inSocket,(struct sockaddr *)&server,length)<0){ + enabled=false; + return false; + } + enabled=true; + return true; +} + +void UdpServer::close(){ + int ret=::close(inSocket); + if(ret != 0) + printf("Error while closing socket, errno: %d\n", errno);//Stop receiving data for this socket. If further data arrives, reject it. + inSocket=0; +} + +int UdpServer::waitUntilReady(bool readyForReading, int timeoutMsecs){ +// If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + if(enabled==false) + return -1; + if(timeoutMsecs<0) + return select(inSocket+1, &stReadFDS, NULL, NULL, NULL); //calling this with a NULL timeout will block indefinitely + FD_ZERO(&stReadFDS); + FD_SET(inSocket, &stReadFDS); + float timeOutSecs=timeoutMsecs*0.001; + stTimeOut.tv_sec=(long int)timeOutSecs; + timeOutSecs-=(int)timeOutSecs; + long int timeOutUsecs=timeOutSecs*1000000; + stTimeOut.tv_usec=timeOutUsecs; + int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut); +// printf("stTimeOut.tv_sec=%ld, stTimeOut.tv_usec=%ld, descriptorReady: \n",stTimeOut.tv_sec,stTimeOut.tv_usec, descriptorReady); +// return descriptorReady>0 ? (timeOutUsecs-stTimeOut.tv_usec) : descriptorReady; + return descriptorReady>0 ? 1 : descriptorReady; +} + +int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error. + void *destBuffer, + int maxBytesToRead, + bool blockUntilSpecifiedAmountHasArrived) +{ + if(enabled==false) + return -1; + FD_ZERO(&stReadFDS); + FD_SET(inSocket, &stReadFDS); + int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stZeroTimeOut); //TODO: this is not JUCE-compliant + if(descriptorReady<0){ //an error occurred + return -1; + } + int numberOfBytes=0; +// do + { + if (FD_ISSET(inSocket, &stReadFDS)) + { + // numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength); + numberOfBytes+=recv(inSocket,destBuffer,maxBytesToRead-numberOfBytes,0); + if(numberOfBytes<0) + return -1; + } + } +// while (blockUntilSpecifiedAmountHasArrived && numberOfBytes==maxBytesToRead); + return numberOfBytes; +} +int UdpServer::empty(){ + return empty(0); +} +int UdpServer::empty(int maxCount){ + int count=0; + int n; + do { + if(waitUntilReady(true, 0)==0) + return 0; + float waste; + n=read(&waste, sizeof(float), false); + count++; + } while (n>0 && (maxCount<=0 || maxCount<count)); + printf("socket emptied with %d reads\n", count); + return count; +}
--- a/include/BeagleRT.h Sat Feb 13 01:51:01 2016 +0000 +++ b/include/BeagleRT.h Sun Apr 10 04:08:06 2016 +0200 @@ -271,7 +271,7 @@ * to indicate that audio processing should terminate. Calling BeagleRT_stopAudio() * has the effect of setting this to \c true. */ -extern bool gShouldStop; +extern int gShouldStop; // *** User-defined render functions ***
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/IirFilter.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,86 @@ +/* + * IirFilter.h + * + * Created on: 17 Sep 2015 + * Author: giulio + */ + +#ifndef IIRFILTER_H_ +#define IIRFILTER_H_ + +#define IIR_FILTER_STAGE_COEFFICIENTS (5) +#define IIR_FILTER_STAGE_STATES (IIR_FILTER_STAGE_COEFFICIENTS - 1) + +class IirFilterStage{ //TODO : to save (some) memory we should only store the coefficients pointers here, + //so that IirFilter can share them among multiple stages if needbe) +private: + double coefficients[IIR_FILTER_STAGE_COEFFICIENTS]; // these are b0,b1,b2,a1,a2 + double states[IIR_FILTER_STAGE_STATES]; // these are xprev, xprevprev, yprev, yprevprev +public: + IirFilterStage(); + void setCoefficients(double* newCoefficients); + void setStates(double* newStates); + // this is not meant to be efficient, just of practical use! + double process(double in){ + process(&in, 1); + return in; + } + + void process(double* inout, int length){ + // make variables explicit. A smart compiler will optimize these out, right? + double b0=coefficients[0]; + double b1=coefficients[1]; + double b2=coefficients[2]; + double a1=coefficients[3]; + double a2=coefficients[4]; + double x1 = states[0]; + double x2= states[1]; + double y1 = states[2]; + double y2 = states[3]; + for(int n = 0; n < length; n++){ + double x0 = inout[n]; + double y = x0 * b0 + x1 * b1 + x2 * b2 + + - y1 * a1 - y2 * a2; + inout[n] = y; + x2 = x1; + x1 = x0; + y2 = y1; + y1 = y; + } + states[0] = x1; + states[1] = x2; + states[2] = y1; + states[3] = y2; + } +}; + +class IirFilter{ +private: + struct IirFilterStage** stages; + int numberOfStages; + void dealloc(); +public: + IirFilter(); + IirFilter(int newNumberOfStages); + IirFilter(int newNumberOfStages, double *newCoefficients); + void setCoefficients(double* newCoefficients); + void setStates(double* newStates); + void setNumberOfStages(int newNumberOfStages); +// double process(double in); +// inline void process(double* inout, int length); +// inline void process(double* in, double* out, int length); + double process(double in){ + process(&in, 1); + return in; + }; + void process(double* inout, int length){ + for(int n = 0; n < numberOfStages && n < 8/* TODO: this "8" compensates for a memory corruption somewhere on the BBB*/; n++){ + stages[n]->process(inout, length); + } + } +}; + + +//void IirFilter::process(double* in, double* out, int length); + +#endif /* IIRFILTER_H_ */
--- a/include/Midi.h Sat Feb 13 01:51:01 2016 +0000 +++ b/include/Midi.h Sun Apr 10 04:08:06 2016 +0200 @@ -115,6 +115,9 @@ unsigned int readPointer; unsigned int elapsedDataBytes; bool waitingForStatus; + void (*messageReadyCallback)(MidiChannelMessage,void*); + bool callbackEnabled; + void* callbackArg; public: MidiParser(){ waitingForStatus = true; @@ -122,6 +125,9 @@ messages.resize(100); // 100 is the number of messages that can be buffered writePointer = 0; readPointer = 0; + callbackEnabled = false; + messageReadyCallback = NULL; + callbackArg = NULL; } /** @@ -133,23 +139,66 @@ * @return the number of bytes parsed */ int parse(midi_byte_t* input, unsigned int length); - int callme(){ - return readPointer; + + /** + * Sets the callback to call when a new MidiChannelMessage is available + * from the input port. + * + * The callback will be called with two arguments: + * callback(MidiChannelMessage newMessage, void* arg) + * + * In order to deactivate the callback, call this method with NULL as the + * first argument. + * While the callback is enabled, calling numAvailableMessages() and + * getNextChannelMessage() is still possible, but it will probably always + * return 0 as the callback is called as soon as a new message is available. + * + * @param newCallback the callback function. + * @param arg the second argument to be passed to the callback function. + * + */ + void setCallback(void (*newCallback)(MidiChannelMessage, void*), void* arg=NULL){ + callbackArg = arg; + messageReadyCallback = newCallback; + if(newCallback != NULL){ + callbackEnabled = true; + } else { + callbackEnabled = false; + } }; + + /** + * Checks whether there is a callback currently set to be called + * every time a new input MidiChannelMessage is available from the + * input port. + */ + bool isCallbackEnabled(){ + return callbackEnabled; + }; + + /** + * Returns the number of unread MidiChannelMessage available from the + * input port. + * + */ + int numAvailableMessages(){ int num = (writePointer - readPointer + messages.size() ) % messages.size(); if(num > 0){ int a = a +1; - a = callme(); + a = readPointer; } return num; } + /** * Get the oldest channel message in the buffer. * * If this method is called when numAvailableMessages()==0, then * a message with all fields set to zero is returned. + * * @param type the type of the message to retrieve + * * @return a copy of the oldest message of the give type in the buffer */ MidiChannelMessage getNextChannelMessage(/*MidiMessageType type*/){ @@ -203,6 +252,21 @@ MidiParser* getParser(); /** + * Sets the callback to call when a new MidiChannelMessage is available + * from the input port. + * + * Internally, it calls enableParser() and the MidiParser::setCallback(); + * + * @param newCallback the callback function. + * @param arg the second argument to be passed to the callback function. + */ + void setParserCallback(void (*callback)(MidiChannelMessage, void*), void* arg=NULL){ + // if callback is not NULL, also enable the parser + enableParser(callback != NULL); //this needs to be first, as it deletes the parser(if exists) + getParser()->setCallback(callback, arg); + } + + /** * Open the specified input Midi port and start reading from it. * @param port Midi port to open * @return 1 on success, -1 on failure
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/NetworkSend.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,115 @@ +//scope.cpp +#ifndef SCOPE_H_ +#define SCOPE_H_ + +#ifdef USE_JUCE +#include <JuceHeader.h> +#else +#include <BeagleRT.h> +#include <rtdk.h> +#include <cmath> +#include <UdpClient.h> +#include <vector> +#include <string> +extern int gShouldStop; +#endif /* USE_JUCE */ + +#define NETWORK_AUDIO_BUFFER_SIZE 302 +#define UDP_BUFFER_HEADER_CHANNEL_INDEX 0 +#define UDP_BUFFER_HEADER_TIMESTAMP_INDEX 1 +#define UDP_BUFFER_HEADER_LENGTH 2 + +struct NetworkBuffer{ + int channelNumber; + int numBuffers; + int writeBuffer; + int readBuffer; + int writePointer; + float** buffers; + bool* doneOnTime; + bool* readyToBeSent; + bool enabled; + int sampleCount; + static const int bufferLength=NETWORK_AUDIO_BUFFER_SIZE; + static const int headerLength=UDP_BUFFER_HEADER_LENGTH; + static const int headerChannelIndex=UDP_BUFFER_HEADER_CHANNEL_INDEX; + static const int headerTimestampIndex=UDP_BUFFER_HEADER_TIMESTAMP_INDEX; +}; + +#ifdef USE_JUCE +class NetworkSend: public Thread { +#else +class NetworkSend { +#endif /* USE_JUCE */ + float sampleRate; +#ifdef USE_JUCE + DatagramSocket udpClient; + int sleepTimeMs; + String remoteHostname; + int remotePortNumber; +#else + UdpClient udpClient; + bool isThreadRunning(); + static int sleepTimeMs; + static bool threadShouldExit(); + static bool threadIsExiting; + static bool threadRunning; + static bool staticConstructed; + static void staticConstructor(); + static AuxiliaryTask sendDataTask; //TODO: allow different AuxiliaryTasks for different priorities (e.g.: audio vs scope) + static std::vector<NetworkSend *> objAddrs; +#endif /* USE_JUCE */ + void dealloc(); +public: + NetworkBuffer channel; +#ifdef USE_JUCE + NetworkSend(const String &threadName); +#else + NetworkSend(); +#endif + ~NetworkSend(); + void setup(float aSampleRate, int blockSize, int aChannelNumber, int aPort, const char *aServer); + void cleanup(); + void sendData(); + void log(float value); + void setPort(int aPort); + void setServer(const char* aServer); + void setChannelNumber(int aChannelNumber); + int getChannelNumber(); + int getTimestamp(); +#ifdef USE_JUCE + void run(); +#else + static int getNumInstances(); + static void sendAllData(); + static void startThread(); + static void stopThread(); + static void run(); +#endif /* USE_JUCE */ +}; + +#ifdef USE_JUCE +#else +/** + * An array of NetworkSend objects with some default parameters + * + * All sending on the same port (defaults to 9999) + * All sending to the same server (defaults to 127.0.0.1) +*/ +class Scope { + std::vector<NetworkSend> channels; + void deallocate(); +public: + Scope(int aNumChannels); + ~Scope(); + void log(int channel, float value); + void setup(); + void setup(float sampleRate, int aPort, const char* aServer); + void sendData(); + void setPort(int port); + void setPort(int channel, int port); + int getNumChannels(); +}; +#endif /* USE_JUCE */ + +#endif /* SCOPE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/ReceiveAudioThread.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,105 @@ +#ifndef RECEIVEAUDIOTHREAD_H_INCLUDED +#define RECEIVEAUDIOTHREAD_H_INCLUDED + +#ifdef USE_JUCE +#include <JuceHeader.h> +#else +#include <BeagleRT.h> +#include <UdpServer.h> +#include <vector> +#include <iostream> +#include <native/task.h> +#include <native/timer.h> +#include <math.h> + +#endif /*USE_JUCE*/ + +#ifdef USE_JUCE +class ReceiveAudioThread : public Thread { +#else +class ReceiveAudioThread{ +#endif /* USE_JUCE */ +private: + // FILE *fd; //DEBUG + // FILE *fd2; //DEBUG +#ifdef USE_JUCE + DatagramSocket socket; +#else + UdpServer socket; +#endif /* USE_JUCE */ + bool listening; + bool bufferReady; +#ifdef USE_JUCE + bool threadRunning; //do we really need this ? +#else + static bool threadRunning; + static bool threadIsExiting; +#endif + float *buffer; + float *stackBuffer; + int bufferLength; + float readPointer; + int writePointer; + int lastValidPointer; +#ifdef USE_JUCE + int sleepTime; +#else + static int sleepTime; +#endif + int waitForSocketTime; + int payloadLength; //size of the payload of each datagram + int headerLength; //size of the header of each datagram + int bytesToRead; + int threadPriority; + int channel; + int timestamp; + void dealloc(); + void wrapWritePointer(); + void pushPayload(int startIndex); + void popPayload(int startIndex); + int readUdpToBuffer(); +#ifdef USE_JUCE +#else + RTIME lastTime; // Used for clock synchronization + static bool threadShouldExit(); + static bool staticConstructed; + static void staticConstructor(); + static AuxiliaryTask receiveDataTask; //TODO: allow different AuxiliaryTasks for different priorities (e.g.: audio vs scope) + static std::vector<ReceiveAudioThread *> objAddrs; +#endif +public: +#ifdef USE_JUCE + ReceiveAudioThread(const String &threadName); +#else + ReceiveAudioThread(); +#endif + ~ReceiveAudioThread(); + void init(int port, int aSamplesPerBlock, int channel); + void bindToPort(int aPort); + bool isListening(); + float* getCurrentBuffer(int length); + /** + * Copies the samples to a non-interleaved buffer. + */ + int getSamplesSrc(float *destination, int length, float samplingRateRatio); + /** + * Copies the samples to an interleaved buffer. + */ + int getSamplesSrc(float *destination, int length, + float samplingRateRatio, int numChannelsInDestination, + int channelToWriteTo); + bool isBufferReady(); + int getTimestamp(); +#ifdef USE_JUCE // if we are in Juce, then we run a separate thread for each receiver + // (as each of them are typically receiving on a mono or stereo track) + void run(); +#else + RTIME getLastTime(); + void static run(); //while in BeagleRT we have a single thread that receives for all the instances. + //TODO: make run() private in BeagleRT + static void startThread(); + static void stopThread(); + static int getNumInstances(); +#endif // USE_JUCE +}; +#endif // RECEIVEAUDIOTHREAD_H_INCLUDED
--- a/include/Scope.h Sat Feb 13 01:51:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -//scope.cpp -#include <BeagleRT.h> -#include <rtdk.h> -#include <cmath> -#include <UdpClient.h> - -#define BUILD_FOR_UDPRECEIVE_PLUGIN -#define NETWORK_AUDIO_BUFFER_SIZE 302 -struct networkAudio{ - int timestamp; - int currentBuffer; - int index; - float buffers[2][NETWORK_AUDIO_BUFFER_SIZE]; - int doneOnTime; - bool toBeSent; - UdpClient udpClient; -}; - -#define NUM_SCOPE_CHANNELS 6 - -static void SendScopeData(); - -class Scope { - int sampleCount; - float sampleRate; - AuxiliaryTask scopeTask; - public: - int numChannels; - networkAudio channel[NUM_SCOPE_CHANNELS]; - Scope(){ - numChannels = NUM_SCOPE_CHANNELS; - sampleCount = 0; -#ifdef BUILD_FOR_UDPRECEIVE_PLUGIN - char server[]="192.168.7.1"; -#else - char server[]="127.0.0.1"; -#endif /* BUILD_FOR_UDPRECEIVE_PLUGIN */ - printf("Sending messages to : %s\n", server); - for(int n=0; n<numChannels; n++){ - channel[n].doneOnTime=1; - channel[n].index=2; //leave space for the heading message (channel, timestamp) - channel[n].timestamp=0; - channel[n].currentBuffer=0; - channel[n].toBeSent=false; - channel[n].udpClient.setServer(server); -#ifdef BUILD_FOR_UDPRECEIVE_PLUGIN - channel[n].udpClient.setPort(9999+n); -#else - channel[n].udpClient.setPort(9999); -#endif /* BUILD_FOR_UDPRECEIVE_PLUGIN */ - } - } - void setup(float _sampleRate); - void log(float channel1=0.0, float channel2=0.0, float channel3=0.0, float channel4=0.0, float channel5=0.0, float channel6=0.0){ - - for(int j=0; j<numChannels; j++){ - if(channel[j].index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ... - channel[j].buffers[channel[j].currentBuffer][0] = (float)j; - channel[j].buffers[channel[j].currentBuffer][1] = (float)channel[j].timestamp; - channel[j].toBeSent=true; - channel[j].index=2; //reset the counter - if(channel[j].doneOnTime==0) - rt_printf("Network buffer underrun :-{\n"); - channel[j].timestamp=sampleCount; - channel[j].currentBuffer=!channel[j].currentBuffer; //switch buffer - channel[j].doneOnTime=0; - BeagleRT_scheduleAuxiliaryTask(scopeTask); //send the buffer - } - } - - channel[0].buffers[channel[0].currentBuffer][channel[0].index++]=channel1; - channel[1].buffers[channel[1].currentBuffer][channel[1].index++]=channel2; - channel[2].buffers[channel[2].currentBuffer][channel[2].index++]=channel3; - channel[3].buffers[channel[3].currentBuffer][channel[3].index++]=channel4; - channel[4].buffers[channel[4].currentBuffer][channel[4].index++]=channel5; - channel[5].buffers[channel[5].currentBuffer][channel[5].index++]=channel6; - - sampleCount++; - } -}; - -Scope* gOscilloscopeInstance; - -void Scope::setup(float _sampleRate){ - sampleRate = _sampleRate; - gOscilloscopeInstance = this; - scopeTask = BeagleRT_createAuxiliaryTask(*SendScopeData, 98, "transmit-receive-audio"); -} - -//Scope scope; - -static void SendScopeData(){ - for(int n=0; n<gOscilloscopeInstance->numChannels; n++){ - if(gOscilloscopeInstance->channel[n].toBeSent){ - gOscilloscopeInstance->channel[n].toBeSent=false; - gOscilloscopeInstance->channel[n].udpClient.send( - gOscilloscopeInstance->channel[n].buffers[!gOscilloscopeInstance->channel[n].currentBuffer], - NETWORK_AUDIO_BUFFER_SIZE*sizeof(float) - ); - gOscilloscopeInstance->channel[n].doneOnTime=1; - } - } -}
--- a/include/UdpClient.h Sat Feb 13 01:51:01 2016 +0000 +++ b/include/UdpClient.h Sun Apr 10 04:08:06 2016 +0200 @@ -23,6 +23,8 @@ int port; int enabled; int outSocket; + struct timeval stTimeOut; + fd_set stWriteFDS; bool isSetPort; bool isSetServer; struct sockaddr_in destinationServer; @@ -33,6 +35,8 @@ void setPort(int aPort); void setServer(const char* aServerName); int send(void* message, int size); + int write(const char* remoteHostname, int remotePortNumber, void* sourceBuffer, int numBytesToWrite); + int waitUntilReady(bool readyForReading, int timeoutMsecs); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/UdpServer.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,70 @@ +/* + * udpServer.h + * + * Created on: 19 May 2015 + * Author: giulio moro + */ + +#ifndef UDPSERVER_H_ +#define UDPSERVER_H_ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +class UdpServer{ + private: + int port; + int enabled; + int inSocket; + struct sockaddr_in server; + struct timeval stTimeOut; + struct timeval stZeroTimeOut; + fd_set stReadFDS; + int size; + void *wasteBuffer; + int wasteBufferSize; + int length; + socklen_t fromLength; + struct sockaddr_in from; + public: + UdpServer(); + UdpServer(int aPort); + ~UdpServer(); + bool init(int aPort); + bool bindToPort(int aPort); + int getBoundPort() const; + /* + * Reads bytes from the socket. + * + * Drop-in replacement for JUCE DatagramSocket::read() + * + If blockUntilSpecifiedAmountHasArrived is true, the method will block until maxBytesToRead + bytes have been read, (or until an error occurs). If this flag is false, the method will + return as much data as is currently available without blocking. + */ + int read(void* destBuffer, int maxBytesToRead, bool blockUntilSpecifiedAmountHasArrived); + void close(); + int empty(); + int empty(int maxCount); + /* + * Waits until the socket is ready for reading or writing. + * + Drop-in replacement for JUCE DatagramSocket::waitUntilReady. + If readyForReading is true, it will wait until the socket is ready for reading; if false, it will wait until it's ready for writing. + If the timeout is < 0, it will wait forever, or else will give up after the specified time. + If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + */ + int waitUntilReady(bool readyForReading, int timeoutMsecs); +}; + + + +#endif /* UDPSERVER_H_ */
--- a/projects/basic_button/render.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/basic_button/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -20,6 +20,10 @@ bool setup(BeagleRTContext *context, void *userData) { + for(unsigned int n=0; n<context->digitalFrames; n++){ + pinModeFrame(context, 0, P8_08, INPUT); + pinModeFrame(context, 0, P8_07, OUTPUT); + } return true; } @@ -39,11 +43,9 @@ void render(BeagleRTContext *context, void *userData) { for(unsigned int n=0; n<context->digitalFrames; n++){ - pinModeFrame(context, 0, P8_08, INPUT); - int status=digitalReadFrame(context, 0, P8_08); //read the value of the button - pinModeFrame(context, 0, P8_07, OUTPUT); - digitalWriteFrame(context, n, P8_07, status); //write the status to the LED - } + int status=digitalReadFrame(context, 0, P8_08); //read the value of the button + digitalWriteFrame(context, n, P8_07, status); //write the status to the LED + } } // cleanup() is called once at the end, after the audio has stopped.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_libpd/m_pd.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,770 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __m_pd_h_ + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +extern "C" { +#endif + +#define PD_MAJOR_VERSION 0 +#define PD_MINOR_VERSION 46 +#define PD_BUGFIX_VERSION 6 +#define PD_TEST_VERSION "" +extern int pd_compatibilitylevel; /* e.g., 43 for pd 0.43 compatibility */ + +/* old name for "MSW" flag -- we have to take it for the sake of many old +"nmakefiles" for externs, which will define NT and not MSW */ +#if defined(NT) && !defined(MSW) +#define MSW +#endif + +/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans@at.or.at> */ +#ifdef _MSC_VER +/* #pragma warning( disable : 4091 ) */ +#pragma warning( disable : 4305 ) /* uncast const double to float */ +#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */ +#pragma warning( disable : 4101 ) /* unused automatic variables */ +#endif /* _MSC_VER */ + + /* the external storage class is "extern" in UNIX; in MSW it's ugly. */ +#ifdef _WIN32 +#ifdef PD_INTERNAL +#define EXTERN __declspec(dllexport) extern +#else +#define EXTERN __declspec(dllimport) extern +#endif /* PD_INTERNAL */ +#else +#define EXTERN extern +#endif /* _WIN32 */ + + /* and depending on the compiler, hidden data structures are + declared differently: */ +#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ ) +#define EXTERN_STRUCT struct +#else +#define EXTERN_STRUCT extern struct +#endif + +/* Define some attributes, specific to the compiler */ +#if defined(__GNUC__) +#define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b))) +#else +#define ATTRIBUTE_FORMAT_PRINTF(a, b) +#endif + +#if !defined(_SIZE_T) && !defined(_SIZE_T_) +#include <stddef.h> /* just for size_t -- how lame! */ +#endif + +/* Microsoft Visual Studio is not C99, it does not provide stdint.h */ +#ifdef _MSC_VER +typedef signed __int8 int8_t; +typedef signed __int16 int16_t; +typedef signed __int32 int32_t; +typedef signed __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +# include <stdint.h> +#endif + +/* for FILE, needed by sys_fopen() and sys_fclose() only */ +#include <stdio.h> + +#define MAXPDSTRING 1000 /* use this for anything you want */ +#define MAXPDARG 5 /* max number of args we can typecheck today */ + +/* signed and unsigned integer types the size of a pointer: */ +#if !defined(PD_LONGINTTYPE) +#define PD_LONGINTTYPE long +#endif + +#if !defined(PD_FLOATSIZE) + /* normally, our floats (t_float, t_sample,...) are 32bit */ +# define PD_FLOATSIZE 32 +#endif + +#if PD_FLOATSIZE == 32 +# define PD_FLOATTYPE float +/* an unsigned int of the same size as FLOATTYPE: */ +# define PD_FLOATUINTTYPE unsigned int + +#elif PD_FLOATSIZE == 64 +# define PD_FLOATTYPE double +# define PD_FLOATUINTTYPE unsigned long +#else +# error invalid FLOATSIZE: must be 32 or 64 +#endif + +typedef PD_LONGINTTYPE t_int; /* pointer-size integer */ +typedef PD_FLOATTYPE t_float; /* a float type at most the same size */ +typedef PD_FLOATTYPE t_floatarg; /* float type for function calls */ + +typedef struct _symbol +{ + char *s_name; + struct _class **s_thing; + struct _symbol *s_next; +} t_symbol; + +EXTERN_STRUCT _array; +#define t_array struct _array /* g_canvas.h */ + +/* pointers to glist and array elements go through a "stub" which sticks +around after the glist or array is freed. The stub itself is deleted when +both the glist/array is gone and the refcount is zero, ensuring that no +gpointers are pointing here. */ + +#define GP_NONE 0 /* the stub points nowhere (has been cut off) */ +#define GP_GLIST 1 /* the stub points to a glist element */ +#define GP_ARRAY 2 /* ... or array */ + +typedef struct _gstub +{ + union + { + struct _glist *gs_glist; /* glist we're in */ + struct _array *gs_array; /* array we're in */ + } gs_un; + int gs_which; /* GP_GLIST/GP_ARRAY */ + int gs_refcount; /* number of gpointers pointing here */ +} t_gstub; + +typedef struct _gpointer /* pointer to a gobj in a glist */ +{ + union + { + struct _scalar *gp_scalar; /* scalar we're in (if glist) */ + union word *gp_w; /* raw data (if array) */ + } gp_un; + int gp_valid; /* number which must match gpointee */ + t_gstub *gp_stub; /* stub which points to glist/array */ +} t_gpointer; + +typedef union word +{ + t_float w_float; + t_symbol *w_symbol; + t_gpointer *w_gpointer; + t_array *w_array; + struct _binbuf *w_binbuf; + int w_index; +} t_word; + +typedef enum +{ + A_NULL, + A_FLOAT, + A_SYMBOL, + A_POINTER, + A_SEMI, + A_COMMA, + A_DEFFLOAT, + A_DEFSYM, + A_DOLLAR, + A_DOLLSYM, + A_GIMME, + A_CANT +} t_atomtype; + +#define A_DEFSYMBOL A_DEFSYM /* better name for this */ + +typedef struct _atom +{ + t_atomtype a_type; + union word a_w; +} t_atom; + +EXTERN_STRUCT _class; +#define t_class struct _class + +EXTERN_STRUCT _outlet; +#define t_outlet struct _outlet + +EXTERN_STRUCT _inlet; +#define t_inlet struct _inlet + +EXTERN_STRUCT _binbuf; +#define t_binbuf struct _binbuf + +EXTERN_STRUCT _clock; +#define t_clock struct _clock + +EXTERN_STRUCT _outconnect; +#define t_outconnect struct _outconnect + +EXTERN_STRUCT _glist; +#define t_glist struct _glist +#define t_canvas struct _glist /* LATER lose this */ + +typedef t_class *t_pd; /* pure datum: nothing but a class pointer */ + +typedef struct _gobj /* a graphical object */ +{ + t_pd g_pd; /* pure datum header (class) */ + struct _gobj *g_next; /* next in list */ +} t_gobj; + +typedef struct _scalar /* a graphical object holding data */ +{ + t_gobj sc_gobj; /* header for graphical object */ + t_symbol *sc_template; /* template name (LATER replace with pointer) */ + t_word sc_vec[1]; /* indeterminate-length array of words */ +} t_scalar; + +typedef struct _text /* patchable object - graphical, with text */ +{ + t_gobj te_g; /* header for graphical object */ + t_binbuf *te_binbuf; /* holder for the text */ + t_outlet *te_outlet; /* linked list of outlets */ + t_inlet *te_inlet; /* linked list of inlets */ + short te_xpix; /* x&y location (within the toplevel) */ + short te_ypix; + short te_width; /* requested width in chars, 0 if auto */ + unsigned int te_type:2; /* from defs below */ +} t_text; + +#define T_TEXT 0 /* just a textual comment */ +#define T_OBJECT 1 /* a MAX style patchable object */ +#define T_MESSAGE 2 /* a MAX stype message */ +#define T_ATOM 3 /* a cell to display a number or symbol */ + +#define te_pd te_g.g_pd + + /* t_object is synonym for t_text (LATER unify them) */ + +typedef struct _text t_object; + +#define ob_outlet te_outlet +#define ob_inlet te_inlet +#define ob_binbuf te_binbuf +#define ob_pd te_g.g_pd +#define ob_g te_g + +typedef void (*t_method)(void); +typedef void *(*t_newmethod)( void); + +/* in ARM 64 a varargs prototype generates a different function call sequence +from a fixed one, so in that special case we make a more restrictive +definition for t_gotfn. This will break some code in the "chaos" package +in Pd extended. (that code will run incorrectly anyhow so why not catch it +at compile time anyhow.) */ +#if defined(__APPLE__) && defined(__aarch64__) +typedef void (*t_gotfn)(void *x); +#else +typedef void (*t_gotfn)(void *x, ...); +#endif + +/* ---------------- pre-defined objects and symbols --------------*/ +EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */ +EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */ +EXTERN t_symbol s_pointer; +EXTERN t_symbol s_float; +EXTERN t_symbol s_symbol; +EXTERN t_symbol s_bang; +EXTERN t_symbol s_list; +EXTERN t_symbol s_anything; +EXTERN t_symbol s_signal; +EXTERN t_symbol s__N; +EXTERN t_symbol s__X; +EXTERN t_symbol s_x; +EXTERN t_symbol s_y; +EXTERN t_symbol s_; + +/* --------- prototypes from the central message system ----------- */ +EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv); +EXTERN t_symbol *gensym(const char *s); +EXTERN t_gotfn getfn(t_pd *x, t_symbol *s); +EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s); +EXTERN void nullfn(void); +EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...); + +/* the following macrose are for sending non-type-checkable mesages, i.e., +using function lookup but circumventing type checking on arguments. Only +use for internal messaging protected by A_CANT so that the message can't +be generated at patch level. */ +#define mess0(x, s) ((*getfn((x), (s)))((x))) +typedef void (*t_gotfn1)(void *x, void *arg1); +#define mess1(x, s, a) ((*(t_gotfn1)getfn((x), (s)))((x), (a))) +typedef void (*t_gotfn2)(void *x, void *arg1, void *arg2); +#define mess2(x, s, a,b) ((*(t_gotfn2)getfn((x), (s)))((x), (a),(b))) +typedef void (*t_gotfn3)(void *x, void *arg1, void *arg2, void *arg3); +#define mess3(x, s, a,b,c) ((*(t_gotfn3)getfn((x), (s)))((x), (a),(b),(c))) +typedef void (*t_gotfn4)(void *x, + void *arg1, void *arg2, void *arg3, void *arg4); +#define mess4(x, s, a,b,c,d) \ + ((*(t_gotfn4)getfn((x), (s)))((x), (a),(b),(c),(d))) +typedef void (*t_gotfn5)(void *x, + void *arg1, void *arg2, void *arg3, void *arg4, void *arg5); +#define mess5(x, s, a,b,c,d,e) \ + ((*(t_gotfn5)getfn((x), (s)))((x), (a),(b),(c),(d),(e))) + +EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_pd *pd_newest(void); + +/* --------------- memory management -------------------- */ +EXTERN void *getbytes(size_t nbytes); +EXTERN void *getzbytes(size_t nbytes); +EXTERN void *copybytes(void *src, size_t nbytes); +EXTERN void freebytes(void *x, size_t nbytes); +EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize); + +/* -------------------- atoms ----------------------------- */ + +#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0) +#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0) +#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \ + (atom)->a_w.w_gpointer = (gp)) +#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f)) +#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \ + (atom)->a_w.w_symbol = (s)) +#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \ + (atom)->a_w.w_index = (n)) +#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \ + (atom)->a_w.w_symbol= (s)) + +EXTERN t_float atom_getfloat(t_atom *a); +EXTERN t_int atom_getint(t_atom *a); +EXTERN t_symbol *atom_getsymbol(t_atom *a); +EXTERN t_symbol *atom_gensym(t_atom *a); +EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv); +EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv); +EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv); + +EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize); + +/* ------------------ binbufs --------------- */ + +EXTERN t_binbuf *binbuf_new(void); +EXTERN void binbuf_free(t_binbuf *x); +EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y); + +EXTERN void binbuf_text(t_binbuf *x, char *text, size_t size); +EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp); +EXTERN void binbuf_clear(t_binbuf *x); +EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...); +EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y); +EXTERN void binbuf_addsemi(t_binbuf *x); +EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv); +EXTERN void binbuf_print(t_binbuf *x); +EXTERN int binbuf_getnatom(t_binbuf *x); +EXTERN t_atom *binbuf_getvec(t_binbuf *x); +EXTERN int binbuf_resize(t_binbuf *x, int newsize); +EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv); +EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_read_via_canvas(t_binbuf *b, char *filename, t_canvas *canvas, + int crflag); +EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname, + int crflag); +EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir, + int crflag); +EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir); +EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, + int tonew); + +/* ------------------ clocks --------------- */ + +EXTERN t_clock *clock_new(void *owner, t_method fn); +EXTERN void clock_set(t_clock *x, double systime); +EXTERN void clock_delay(t_clock *x, double delaytime); +EXTERN void clock_unset(t_clock *x); +EXTERN void clock_setunit(t_clock *x, double timeunit, int sampflag); +EXTERN double clock_getlogicaltime(void); +EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */ +EXTERN double clock_gettimesince(double prevsystime); +EXTERN double clock_gettimesincewithunits(double prevsystime, + double units, int sampflag); +EXTERN double clock_getsystimeafter(double delaytime); +EXTERN void clock_free(t_clock *x); + +/* ----------------- pure data ---------------- */ +EXTERN t_pd *pd_new(t_class *cls); +EXTERN void pd_free(t_pd *x); +EXTERN void pd_bind(t_pd *x, t_symbol *s); +EXTERN void pd_unbind(t_pd *x, t_symbol *s); +EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c); +EXTERN void pd_pushsym(t_pd *x); +EXTERN void pd_popsym(t_pd *x); +EXTERN t_symbol *pd_getfilename(void); +EXTERN t_symbol *pd_getdirname(void); +EXTERN void pd_bang(t_pd *x); +EXTERN void pd_pointer(t_pd *x, t_gpointer *gp); +EXTERN void pd_float(t_pd *x, t_float f); +EXTERN void pd_symbol(t_pd *x, t_symbol *s); +EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv); +#define pd_class(x) (*(x)) + +/* ----------------- pointers ---------------- */ +EXTERN void gpointer_init(t_gpointer *gp); +EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto); +EXTERN void gpointer_unset(t_gpointer *gp); +EXTERN int gpointer_check(const t_gpointer *gp, int headok); + +/* ----------------- patchable "objects" -------------- */ +EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, + t_symbol *s2); +EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); +EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp); +EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); +EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f); +EXTERN void inlet_free(t_inlet *x); + +EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s); +EXTERN void outlet_bang(t_outlet *x); +EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp); +EXTERN void outlet_float(t_outlet *x, t_float f); +EXTERN void outlet_symbol(t_outlet *x, t_symbol *s); +EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv); +EXTERN t_symbol *outlet_getsymbol(t_outlet *x); +EXTERN void outlet_free(t_outlet *x); +EXTERN t_object *pd_checkobject(t_pd *x); + + +/* -------------------- canvases -------------- */ + +EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir); + +EXTERN void canvas_setargs(int argc, t_atom *argv); +EXTERN void canvas_getargs(int *argcp, t_atom **argvp); +EXTERN t_symbol *canvas_getcurrentdir(void); +EXTERN t_glist *canvas_getcurrent(void); +EXTERN void canvas_makefilename(t_glist *c, char *file, + char *result,int resultsize); +EXTERN t_symbol *canvas_getdir(t_glist *x); +EXTERN char sys_font[]; /* default typeface set in s_main.c */ +EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */ +EXTERN int sys_fontwidth(int fontsize); +EXTERN int sys_fontheight(int fontsize); +EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b); +EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin); + +/* ---------------- widget behaviors ---------------------- */ + +EXTERN_STRUCT _widgetbehavior; +#define t_widgetbehavior struct _widgetbehavior + +EXTERN_STRUCT _parentwidgetbehavior; +#define t_parentwidgetbehavior struct _parentwidgetbehavior +EXTERN t_parentwidgetbehavior *pd_getparentwidget(t_pd *x); + +/* -------------------- classes -------------- */ + +#define CLASS_DEFAULT 0 /* flags for new classes below */ +#define CLASS_PD 1 +#define CLASS_GOBJ 2 +#define CLASS_PATCHABLE 3 +#define CLASS_NOINLET 8 + +#define CLASS_TYPEMASK 3 + + +EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod, + t_method freemethod, size_t size, int flags, t_atomtype arg1, ...); +EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s, + t_atomtype type1, ...); +EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel, + t_atomtype arg1, ...); +EXTERN void class_addbang(t_class *c, t_method fn); +EXTERN void class_addpointer(t_class *c, t_method fn); +EXTERN void class_doaddfloat(t_class *c, t_method fn); +EXTERN void class_addsymbol(t_class *c, t_method fn); +EXTERN void class_addlist(t_class *c, t_method fn); +EXTERN void class_addanything(t_class *c, t_method fn); +EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s); +EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w); +EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w); +EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c); +EXTERN char *class_getname(t_class *c); +EXTERN char *class_gethelpname(t_class *c); +EXTERN char *class_gethelpdir(t_class *c); +EXTERN void class_setdrawcommand(t_class *c); +EXTERN int class_isdrawcommand(t_class *c); +EXTERN void class_domainsignalin(t_class *c, int onset); +EXTERN void class_set_extern_dir(t_symbol *s); +#define CLASS_MAINSIGNALIN(c, type, field) \ + class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0) + + /* prototype for functions to save Pd's to a binbuf */ +typedef void (*t_savefn)(t_gobj *x, t_binbuf *b); +EXTERN void class_setsavefn(t_class *c, t_savefn f); +EXTERN t_savefn class_getsavefn(t_class *c); +EXTERN void obj_saveformat(t_object *x, t_binbuf *bb); /* add format to bb */ + + /* prototype for functions to open properties dialogs */ +typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist); +EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f); +EXTERN t_propertiesfn class_getpropertiesfn(t_class *c); + +#ifndef PD_CLASS_DEF +#define class_addbang(x, y) class_addbang((x), (t_method)(y)) +#define class_addpointer(x, y) class_addpointer((x), (t_method)(y)) +#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y)) +#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y)) +#define class_addlist(x, y) class_addlist((x), (t_method)(y)) +#define class_addanything(x, y) class_addanything((x), (t_method)(y)) +#endif + +/* ------------ printing --------------------------------- */ +EXTERN void post(const char *fmt, ...); +EXTERN void startpost(const char *fmt, ...); +EXTERN void poststring(const char *s); +EXTERN void postfloat(t_floatarg f); +EXTERN void postatom(int argc, t_atom *argv); +EXTERN void endpost(void); +EXTERN void error(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +EXTERN void verbose(int level, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); +EXTERN void bug(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); +EXTERN void pd_error(void *object, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(2, 3); +EXTERN void logpost(const void *object, const int level, const char *fmt, ...) + ATTRIBUTE_FORMAT_PRINTF(3, 4); +EXTERN void sys_logerror(const char *object, const char *s); +EXTERN void sys_unixerror(const char *object); +EXTERN void sys_ouch(void); + + +/* ------------ system interface routines ------------------- */ +EXTERN int sys_isreadablefile(const char *name); +EXTERN int sys_isabsolutepath(const char *dir); +EXTERN void sys_bashfilename(const char *from, char *to); +EXTERN void sys_unbashfilename(const char *from, char *to); +EXTERN int open_via_path(const char *dir, const char *name, const char *ext, + char *dirresult, char **nameresult, unsigned int size, int bin); +EXTERN int sched_geteventno(void); +EXTERN double sys_getrealtime(void); +EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */ + +/* Win32's open()/fopen() do not handle UTF-8 filenames so we need + * these internal versions that handle UTF-8 filenames the same across + * all platforms. They are recommended for use in external + * objectclasses as well so they work with Unicode filenames on Windows */ +EXTERN int sys_open(const char *path, int oflag, ...); +EXTERN int sys_close(int fd); +EXTERN FILE *sys_fopen(const char *filename, const char *mode); +EXTERN int sys_fclose(FILE *stream); + +/* ------------ threading ------------------- */ +EXTERN void sys_lock(void); +EXTERN void sys_unlock(void); +EXTERN int sys_trylock(void); + + +/* --------------- signals ----------------------------------- */ + +typedef PD_FLOATTYPE t_sample; +typedef union _sampleint_union { + t_sample f; + PD_FLOATUINTTYPE i; +} t_sampleint_union; +#define MAXLOGSIG 32 +#define MAXSIGSIZE (1 << MAXLOGSIG) + +typedef struct _signal +{ + int s_n; /* number of points in the array */ + t_sample *s_vec; /* the array */ + t_float s_sr; /* sample rate */ + int s_refcount; /* number of times used */ + int s_isborrowed; /* whether we're going to borrow our array */ + struct _signal *s_borrowedfrom; /* signal to borrow it from */ + struct _signal *s_nextfree; /* next in freelist */ + struct _signal *s_nextused; /* next in used list */ + int s_vecsize; /* allocated size of array in points */ +} t_signal; + +typedef t_int *(*t_perfroutine)(t_int *args); + +EXTERN t_int *plus_perform(t_int *args); +EXTERN t_int *zero_perform(t_int *args); +EXTERN t_int *copy_perform(t_int *args); + +EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n); +EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n); +EXTERN void dsp_add_scalarcopy(t_float *in, t_sample *out, int n); +EXTERN void dsp_add_zero(t_sample *out, int n); + +EXTERN int sys_getblksize(void); +EXTERN t_float sys_getsr(void); +EXTERN int sys_get_inchannels(void); +EXTERN int sys_get_outchannels(void); + +EXTERN void dsp_add(t_perfroutine f, int n, ...); +EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec); +EXTERN void pd_fft(t_float *buf, int npoints, int inverse); +EXTERN int ilog2(int n); + +EXTERN void mayer_fht(t_sample *fz, int n); +EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag); +EXTERN void mayer_realfft(int n, t_sample *real); +EXTERN void mayer_realifft(int n, t_sample *real); + +EXTERN float *cos_table; +#define LOGCOSTABSIZE 9 +#define COSTABSIZE (1<<LOGCOSTABSIZE) + +EXTERN int canvas_suspend_dsp(void); +EXTERN void canvas_resume_dsp(int oldstate); +EXTERN void canvas_update_dsp(void); +EXTERN int canvas_dspstate; + +/* up/downsampling */ +typedef struct _resample +{ + int method; /* up/downsampling method ID */ + + int downsample; /* downsampling factor */ + int upsample; /* upsampling factor */ + + t_sample *s_vec; /* here we hold the resampled data */ + int s_n; + + t_sample *coeffs; /* coefficients for filtering... */ + int coefsize; + + t_sample *buffer; /* buffer for filtering */ + int bufsize; +} t_resample; + +EXTERN void resample_init(t_resample *x); +EXTERN void resample_free(t_resample *x); + +EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method); +EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method); +EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method); + +/* ----------------------- utility functions for signals -------------- */ +EXTERN t_float mtof(t_float); +EXTERN t_float ftom(t_float); +EXTERN t_float rmstodb(t_float); +EXTERN t_float powtodb(t_float); +EXTERN t_float dbtorms(t_float); +EXTERN t_float dbtopow(t_float); + +EXTERN t_float q8_sqrt(t_float); +EXTERN t_float q8_rsqrt(t_float); +#ifndef N32 +EXTERN t_float qsqrt(t_float); /* old names kept for extern compatibility */ +EXTERN t_float qrsqrt(t_float); +#endif +/* --------------------- data --------------------------------- */ + + /* graphical arrays */ +EXTERN_STRUCT _garray; +#define t_garray struct _garray + +EXTERN t_class *garray_class; +EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec); +EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec); +EXTERN void garray_redraw(t_garray *x); +EXTERN int garray_npoints(t_garray *x); +EXTERN char *garray_vec(t_garray *x); +EXTERN void garray_resize(t_garray *x, t_floatarg f); /* avoid; use this: */ +EXTERN void garray_resize_long(t_garray *x, long n); /* better version */ +EXTERN void garray_usedindsp(t_garray *x); +EXTERN void garray_setsaveit(t_garray *x, int saveit); +EXTERN t_glist *garray_getglist(t_garray *x); +EXTERN t_array *garray_getarray(t_garray *x); +EXTERN t_class *scalar_class; + +EXTERN t_float *value_get(t_symbol *s); +EXTERN void value_release(t_symbol *s); +EXTERN int value_getfloat(t_symbol *s, t_float *f); +EXTERN int value_setfloat(t_symbol *s, t_float f); + +/* ------- GUI interface - functions to send strings to TK --------- */ +typedef void (*t_guicallbackfn)(t_gobj *client, t_glist *glist); + +EXTERN void sys_vgui(char *fmt, ...); +EXTERN void sys_gui(char *s); +EXTERN void sys_pretendguibytes(int n); +EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f); +EXTERN void sys_unqueuegui(void *client); + /* dialog window creation and destruction */ +EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd); +EXTERN void gfxstub_deleteforkey(void *key); + +extern t_class *glob_pdobject; /* object to send "pd" messages */ + +/*------------- Max 0.26 compatibility --------------------*/ + +/* the following reflects the new way classes are laid out, with the class + pointing to the messlist and not vice versa. Externs shouldn't feel it. */ +typedef t_class *t_externclass; + +EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine, + t_method freeroutine, t_symbol *name, size_t size, int tiny, \ + t_atomtype arg1, ...); +EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...); + +#define t_getbytes getbytes +#define t_freebytes freebytes +#define t_resizebytes resizebytes +#define typedmess pd_typedmess +#define vmess pd_vmess + +/* A definition to help gui objects straddle 0.34-0.35 changes. If this is +defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */ + +#define PD_USE_TE_XPIX + +#ifndef _MSC_VER /* Microoft compiler can't handle "inline" function/macros */ +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) +/* a test for NANs and denormals. Should only be necessary on i386. */ +# if PD_FLOATSIZE == 32 +static inline int PD_BADFLOAT(t_sample f) { + t_sampleint_union u; + u.f=f; + return ((u.i & 0x7f800000)==0) || ((u.i&0x7f800000)==0x7f800000); +} +/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */ +static inline int PD_BIGORSMALL(t_sample f) { + t_sampleint_union u; + u.f=f; + return ((u.i & 0x60000000)==0) || ((u.i & 0x60000000)==0x60000000); +} +# else +# warning 64bit mode: BIGORSMALL not implemented yet +# define PD_BADFLOAT(f) 0 +# define PD_BIGORSMALL(f) 0 +# endif +#else +# define PD_BADFLOAT(f) 0 +# define PD_BIGORSMALL(f) 0 +#endif +#else /* _MSC_VER */ +#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ + (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) +/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */ +#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ + (((*(unsigned int*)&(f))&0x60000000)==0x60000000)) +#endif /* _MSC_VER */ + /* get version number at run time */ +EXTERN void sys_getversion(int *major, int *minor, int *bugfix); + +EXTERN_STRUCT _pdinstance; +#define t_pdinstance struct _pdinstance /* m_imp.h */ + +/* m_pd.c */ + +EXTERN t_pdinstance *pdinstance_new( void); +EXTERN void pd_setinstance(t_pdinstance *x); +EXTERN void pdinstance_free(t_pdinstance *x); +EXTERN t_canvas *pd_getcanvaslist(void); +EXTERN int pd_getdspstate(void); + +#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) +} +#endif + +#define __m_pd_h_ +#endif /* __m_pd_h_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_libpd/main.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,91 @@ +/* + * default_main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ +#include <unistd.h> +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include "../include/BeagleRT.h" + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "h", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, 0) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_libpd/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,187 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + +#include <BeagleRT.h> +#include <cmath> +#include <Utilities.h> +#include <I2c_Codec.h> +#include <PRU.h> +#include <stdio.h> +#include "z_libpd.h" +#include <UdpServer.h> + +// setup() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. +#define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd + +int gChannelsInUse = 10; +int gBufLength; + +float* gInBuf; +float* gOutBuf; + +void pdnoteon(int ch, int pitch, int vel) { + printf("noteon: %d %d %d\n", ch, pitch, vel); +} + +void BeagleRT_printHook(const char *recv){ + rt_printf("%s", recv); +} + +UdpServer udpServer; + +void udpRead(){ + char dest[100] = {0}; + while(!gShouldStop){ + libpd_sys_microsleep(0); + usleep(1000); + } +} + +AuxiliaryTask udpReadTask; +bool setup(BeagleRTContext *context, void *userData) +{ + gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse); + udpServer.bindToPort(1234); + + // check that we are not running with a blocksize smaller than DEFDACBLKSIZE + // it would still work, but the load would be executed unevenly between calls to render + if(context->audioFrames < DEFDACBLKSIZE){ + fprintf(stderr, "Error: minimum block size must be %d\n", DEFDACBLKSIZE); + return false; + } + + // check that the sampling rate of the analogs is the same as audio if running with + // more than 2 channels (that is with analog). If we fix the TODO in render, then + // this test is not needed. +// if(context->analogFrames != context->audioFrames){ +// fprintf(stderr, "Error: analog and audio sampling rates must be the same\n"); +// return false; +// } + //following lines borrowed from libpd/samples/c/pdtest/pdtest.c + // init pd + libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init + libpd_set_noteonhook(pdnoteon); + libpd_init(); + //TODO: analyse the ASCII of the patch file and find the in/outs to use + libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); + + libpd_start_message(1); // one entry in list + libpd_add_float(1.0f); + libpd_finish_message("pd", "dsp"); + + gBufLength = max(DEFDACBLKSIZE, context->audioFrames); + unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; + gInBuf = (float*)malloc(bufferSize); + gOutBuf = (float*)malloc(bufferSize); + // no need to memset to zero + + char file[] = "_main.pd"; + char folder[] = "./"; + // open patch [; pd open file folder( + libpd_openfile(file, folder); + + udpReadTask = BeagleRT_createAuxiliaryTask(udpRead, 60, "udpReadTask"); + BeagleRT_scheduleAuxiliaryTask(udpReadTask); + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numMatrixFrames +// will be 0. +BeagleRTContext *c; +void render(BeagleRTContext *context, void *userData) +{ + static int inW = 0; + static int outR = 0; +/* + * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers + * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably + * do not need the for loops before and after libpd_process_float, so you can save quite some + * memory operations. + */ + static int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels); + // rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse); + for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved + for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio + gInBuf[inW++] = audioReadFrame(context, n, ch); + } + // then analogs + // this loop resamples by ZOH, as needed, using m + if(context->analogChannels == 8 ){ //hold the value for two frames + for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + gInBuf[inW++] = analogReadFrame(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even + } + } else if(context->analogChannels == 4){ //write every frame + for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + gInBuf[inW++] = analogReadFrame(context, n, analogCh); + } + } else if(context->analogChannels == 2){ //drop every other frame + for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + gInBuf[inW++] = analogReadFrame(context, n*2, analogCh); + } + } + if(inW == gBufLength * gChannelsInUse){ + inW = 0; + } + } + // rt_printf("inW %d\n", inW); + if(inW == 0){ //if the buffer is full, process it + static int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE; + libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); + outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time + } + + for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved + for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ + audioWriteFrame(context, n, ch, gOutBuf[outR++]); + } + //and analogs + if(context->analogChannels == 8){ + for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + float analogOut = gOutBuf[outR++]; + if((n&1) == 0){//write every two frames + analogWriteFrame(context, n/2, analogCh, analogOut); + } else { + // discard this sample + } + } + } else if(context->analogChannels == 4){ //write every frame + for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + float analogOut = gOutBuf[outR++]; + analogWriteFrame(context, n, analogCh, analogOut); + } + } else if(context->analogChannels == 2){ //write twice every frame + for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ + float analogOut = gOutBuf[outR++]; + analogWriteFrame(context, 2*n, analogCh, analogOut); + analogWriteFrame(context, 2*n + 1, analogCh, analogOut); + } + } + if(outR == gBufLength * gChannelsInUse){ + outR = 0; + } + } + // rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", + // outR , analogChannelsInUse, gChannelsInUse); +} + +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). + +void cleanup(BeagleRTContext *context, void *userData) +{ + free(gInBuf); + free(gOutBuf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_libpd/s_stuff.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,411 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Audio and MIDI I/O, and other scheduling and system stuff. */ + +/* NOTE: this file describes Pd implementation details which may change +in future releases. The public (stable) API is in m_pd.h. */ + +/* in s_path.c */ + +typedef struct _namelist /* element in a linked list of stored strings */ +{ + struct _namelist *nl_next; /* next in list */ + char *nl_string; /* the string */ +} t_namelist; + +t_namelist *namelist_append(t_namelist *listwas, const char *s, int allowdup); +t_namelist *namelist_append_files(t_namelist *listwas, const char *s); +void namelist_free(t_namelist *listwas); +char *namelist_get(t_namelist *namelist, int n); +void sys_setextrapath(const char *p); +extern int sys_usestdpath; +extern t_namelist *sys_externlist; +extern t_namelist *sys_searchpath; +extern t_namelist *sys_helppath; +int sys_open_absolute(const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp); +int sys_trytoopenone(const char *dir, const char *name, const char* ext, + char *dirresult, char **nameresult, unsigned int size, int bin); +t_symbol *sys_decodedialog(t_symbol *s); + +/* s_file.c */ + +void sys_loadpreferences( void); +void sys_savepreferences( void); +extern int sys_defeatrt; +extern t_symbol *sys_flags; + +/* s_main.c */ +extern int sys_debuglevel; +extern int sys_verbose; +extern int sys_noloadbang; +extern int sys_nogui; +extern char *sys_guicmd; + +EXTERN int sys_nearestfontsize(int fontsize); +EXTERN int sys_hostfontsize(int fontsize); + +extern int sys_defaultfont; +EXTERN t_symbol *sys_libdir; /* library directory for auxilliary files */ +extern t_symbol *sys_guidir; /* directory holding pd_gui, u_pdsend, etc */ + +/* s_loader.c */ + +typedef int (*loader_t)(t_canvas *canvas, char *classname); /* callback type */ +EXTERN int sys_load_lib(t_canvas *canvas, char *filename); +EXTERN void sys_register_loader(loader_t loader); + +/* s_audio.c */ + +#define SENDDACS_NO 0 /* return values for sys_send_dacs() */ +#define SENDDACS_YES 1 +#define SENDDACS_SLEPT 2 + +#define DEFDACBLKSIZE 8 +extern int sys_schedblocksize; /* audio block size for scheduler */ +extern int sys_hipriority; /* real-time flag, true if priority boosted */ +EXTERN t_sample *sys_soundout; +EXTERN t_sample *sys_soundin; +extern int sys_inchannels; +extern int sys_outchannels; +extern int sys_advance_samples; /* scheduler advance in samples */ +extern int sys_blocksize; /* audio I/O block size in sample frames */ +extern t_float sys_dacsr; +extern int sys_schedadvance; +extern int sys_sleepgrain; +EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev, + int nchindev, int *chindev, + int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, + int srate, int advance, int callback, int blocksize); +/* the same as above, but reopens the audio subsystem if needed */ +EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, + int nchindev, int *chindev, + int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev, + int srate, int advance, int callback, int blocksize); +EXTERN void sys_reopen_audio( void); +EXTERN void sys_close_audio(void); + /* return true if the interface prefers always being open (ala jack) : */ +EXTERN int audio_shouldkeepopen( void); +EXTERN int audio_isopen( void); /* true if audio interface is open */ +EXTERN int sys_audiodevnametonumber(int output, const char *name); +EXTERN void sys_audiodevnumbertoname(int output, int devno, char *name, + int namesize); + +int sys_send_dacs(void); +void sys_reportidle(void); +void sys_set_priority(int higher); +void sys_audiobuf(int nbufs); +void sys_getmeters(t_sample *inmax, t_sample *outmax); +void sys_listdevs(void); +void sys_setblocksize(int n); + +EXTERN void sys_get_audio_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, + int maxndev, int devdescsize); +EXTERN void sys_get_audio_apis(char *buf); + +/* s_midi.c */ +#define MAXMIDIINDEV 16 /* max. number of input ports */ +#define MAXMIDIOUTDEV 16 /* max. number of output ports */ +extern int sys_midiapi; +extern int sys_nmidiin; +extern int sys_nmidiout; +extern int sys_midiindevlist[]; +extern int sys_midioutdevlist[]; + +EXTERN void sys_open_midi(int nmidiin, int *midiinvec, + int nmidiout, int *midioutvec, int enable); + +EXTERN void sys_get_midi_apis(char *buf); +EXTERN void sys_get_midi_devs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, + int maxndev, int devdescsize); +EXTERN void sys_get_midi_params(int *pnmidiindev, int *pmidiindev, + int *pnmidioutdev, int *pmidioutdev); +EXTERN int sys_mididevnametonumber(int output, const char *name); +EXTERN void sys_mididevnumbertoname(int output, int devno, char *name, + int namesize); + +EXTERN void sys_reopen_midi( void); +EXTERN void sys_close_midi( void); +EXTERN void sys_putmidimess(int portno, int a, int b, int c); +EXTERN void sys_putmidibyte(int portno, int a); +EXTERN void sys_poll_midi(void); +EXTERN void sys_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sys_midibytein(int portno, int byte); + + /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */ +void midi_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize); +void sys_do_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev); + +#ifdef USEAPI_ALSA +EXTERN void sys_alsa_putmidimess(int portno, int a, int b, int c); +EXTERN void sys_alsa_putmidibyte(int portno, int a); +EXTERN void sys_alsa_poll_midi(void); +EXTERN void sys_alsa_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sys_alsa_midibytein(int portno, int byte); +EXTERN void sys_alsa_close_midi( void); + + + /* implemented in the system dependent MIDI code (s_midi_pm.c, etc. ) */ +void midi_alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int maxndev, int devdescsize); +void sys_alsa_do_open_midi(int nmidiindev, int *midiindev, + int nmidioutdev, int *midioutdev); +#endif + +/* m_sched.c */ +EXTERN void sys_log_error(int type); +#define ERR_NOTHING 0 +#define ERR_ADCSLEPT 1 +#define ERR_DACSLEPT 2 +#define ERR_RESYNC 3 +#define ERR_DATALATE 4 + +#define SCHED_AUDIO_NONE 0 +#define SCHED_AUDIO_POLL 1 +#define SCHED_AUDIO_CALLBACK 2 +void sched_set_using_audio(int flag); + +/* s_inter.c */ + +EXTERN void sys_microsleep(int microsec); +EXTERN void sys_init_fdpoll(void); + +EXTERN void sys_bail(int exitcode); +EXTERN int sys_pollgui(void); + +EXTERN_STRUCT _socketreceiver; +#define t_socketreceiver struct _socketreceiver + +typedef void (*t_socketnotifier)(void *x, int n); +typedef void (*t_socketreceivefn)(void *x, t_binbuf *b); + +EXTERN t_socketreceiver *socketreceiver_new(void *owner, + t_socketnotifier notifier, t_socketreceivefn socketreceivefn, int udp); +EXTERN void socketreceiver_read(t_socketreceiver *x, int fd); +EXTERN void sys_sockerror(char *s); +EXTERN void sys_closesocket(int fd); + +typedef void (*t_fdpollfn)(void *ptr, int fd); +EXTERN void sys_addpollfn(int fd, t_fdpollfn fn, void *ptr); +EXTERN void sys_rmpollfn(int fd); +#if defined(USEAPI_OSS) || defined(USEAPI_ALSA) +void sys_setalarm(int microsec); +#endif + +#define API_NONE 0 +#define API_ALSA 1 +#define API_OSS 2 +#define API_MMIO 3 +#define API_PORTAUDIO 4 +#define API_JACK 5 +#define API_SGI 6 /* gone */ +#define API_AUDIOUNIT 7 +#define API_ESD 8 /* no idea what this was, probably gone now */ +#define API_DUMMY 9 + + /* figure out which API should be the default. The one we judge most + likely to offer a working device takes precedence so that if you + start up Pd for the first time there's a reasonable chance you'll have + sound. (You'd think portaudio would be best but it seems to default + to jack on linux, and and on Windows we only use it for ASIO). + If nobody shows up, define DUMMY and make it the default.*/ +#if defined(USEAPI_MMIO) +# define API_DEFAULT API_MMIO +# define API_DEFSTRING "MMIO" +#elif defined(USEAPI_ALSA) +# define API_DEFAULT API_ALSA +# define API_DEFSTRING "ALSA" +#elif defined(USEAPI_OSS) +# define API_DEFAULT API_OSS +# define API_DEFSTRING "OSS" +#elif defined(USEAPI_AUDIOUNIT) +# define API_DEFAULT API_AUDIOUNIT +# define API_DEFSTRING "AudioUnit" +#elif defined(USEAPI_ESD) +# define API_DEFAULT API_ESD +# define API_DEFSTRING "ESD (?)" +#elif defined(USEAPI_PORTAUDIO) +# define API_DEFAULT API_PORTAUDIO +# define API_DEFSTRING "portaudio" +#elif defined(USEAPI_JACK) +# define API_DEFAULT API_JACK +# define API_DEFSTRING "Jack audio connection kit" +#else +# ifndef USEAPI_DUMMY /* we need at least one so bring in the dummy */ +# define USEAPI_DUMMY +# endif /* USEAPI_DUMMY */ +# define API_DEFAULT API_DUMMY +# define API_DEFSTRING "dummy audio" +#endif + +#define DEFAULTAUDIODEV 0 + +#define MAXAUDIOINDEV 4 +#define MAXAUDIOOUTDEV 4 + +#define DEFMIDIDEV 0 + +#define DEFAULTSRATE 44100 +#ifdef _WIN32 +#define DEFAULTADVANCE 80 +#else +#ifdef __APPLE__ +#define DEFAULTADVANCE 5 /* this is in addition to their own delay */ +#else +#define DEFAULTADVANCE 25 +#endif +#endif + +typedef void (*t_audiocallback)(void); + +int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin, + t_sample *soundout, int framesperbuf, int nbuffers, + int indeviceno, int outdeviceno, t_audiocallback callback); +void pa_close_audio(void); +int pa_send_dacs(void); +void sys_reportidle(void); +void pa_listdevs(void); +void pa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int oss_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int blocksize); +void oss_close_audio(void); +int oss_send_dacs(void); +void oss_reportidle(void); +void oss_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int alsa_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate, int blocksize); +void alsa_close_audio(void); +int alsa_send_dacs(void); +void alsa_reportidle(void); +void alsa_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int jack_open_audio(int wantinchans, int wantoutchans, int srate, + t_audiocallback callback); +void jack_close_audio(void); +int jack_send_dacs(void); +void jack_reportidle(void); +void jack_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); +void jack_listdevs(void); + +int mmio_open_audio(int naudioindev, int *audioindev, + int nchindev, int *chindev, int naudiooutdev, int *audiooutdev, + int nchoutdev, int *choutdev, int rate, int blocksize); +void mmio_close_audio( void); +void mmio_reportidle(void); +int mmio_send_dacs(void); +void mmio_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void audiounit_close_audio(void); +int audiounit_send_dacs(void); +void audiounit_listdevs(void); +void audiounit_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int esd_open_audio(int naudioindev, int *audioindev, int nchindev, + int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev, + int *choutdev, int rate); +void esd_close_audio(void); +int esd_send_dacs(void); +void esd_listdevs(void); +void esd_getdevs(char *indevlist, int *nindevs, + char *outdevlist, int *noutdevs, int *canmulti, + int maxndev, int devdescsize); + +int dummy_open_audio(int nin, int nout, int sr); +int dummy_close_audio( void); +int dummy_send_dacs( void); +void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist, + int *noutdevs, int *canmulti, int maxndev, int devdescsize); +void dummy_listdevs( void); + +void sys_listmididevs(void); +EXTERN void sys_set_midi_api(int whichapi); +EXTERN void sys_set_audio_api(int whichapi); +EXTERN int sys_audioapi; +EXTERN void sys_set_audio_state(int onoff); + +/* API dependent audio flags and settings */ +void oss_set32bit( void); +void linux_alsa_devname(char *devname); + +EXTERN void sys_get_audio_params( + int *pnaudioindev, int *paudioindev, int *chindev, + int *pnaudiooutdev, int *paudiooutdev, int *choutdev, + int *prate, int *padvance, int *callback, int *blocksize); +void sys_save_audio_params( + int naudioindev, int *audioindev, int *chindev, + int naudiooutdev, int *audiooutdev, int *choutdev, + int rate, int advance, int callback, int blocksize); + +/* s_file.c */ + +typedef void (*t_printhook)(const char *s); +extern t_printhook sys_printhook; /* set this to override printing */ +extern int sys_printtostderr; + +/* jsarlo { */ + +EXTERN double sys_time; +EXTERN double sys_time_per_dsp_tick; +EXTERN int sys_externalschedlib; + +EXTERN t_sample* get_sys_soundout(void ) ; +EXTERN t_sample* get_sys_soundin(void ) ; +EXTERN int* get_sys_main_advance(void ) ; +EXTERN double* get_sys_time_per_dsp_tick(void ) ; +EXTERN int* get_sys_schedblocksize(void ) ; +EXTERN double* get_sys_time(void ) ; +EXTERN t_float* get_sys_dacsr(void ) ; +EXTERN int* get_sys_sleepgrain(void ) ; +EXTERN int* get_sys_schedadvance(void ) ; + +EXTERN void sys_clearhist(void ); +EXTERN void sys_initmidiqueue(void ); +EXTERN int sys_addhist(int phase); +EXTERN void sys_setmiditimediff(double inbuftime, double outbuftime); +EXTERN void sched_tick( void); +EXTERN void sys_pollmidiqueue(void ); +EXTERN int sys_pollgui(void ); +EXTERN void sys_setchsr(int chin, int chout, int sr); + +EXTERN void inmidi_realtimein(int portno, int cmd); +EXTERN void inmidi_byte(int portno, int byte); +EXTERN void inmidi_sysex(int portno, int byte); +EXTERN void inmidi_noteon(int portno, int channel, int pitch, int velo); +EXTERN void inmidi_controlchange(int portno, + int channel, + int ctlnumber, + int value); +EXTERN void inmidi_programchange(int portno, int channel, int value); +EXTERN void inmidi_pitchbend(int portno, int channel, int value); +EXTERN void inmidi_aftertouch(int portno, int channel, int value); +EXTERN void inmidi_polyaftertouch(int portno, + int channel, + int pitch, + int value); +/* } jsarlo */ +extern t_widgetbehavior text_widgetbehavior;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_libpd/z_libpd.h Sun Apr 10 04:08:06 2016 +0200 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010 Peter Brinkmann (peter.brinkmann@gmail.com) + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * See https://github.com/libpd/libpd/wiki for documentation + * + */ + +#ifndef __Z_LIBPD_H__ +#define __Z_LIBPD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "m_pd.h" + +EXTERN int libpd_init(void); +EXTERN void libpd_clear_search_path(void); +EXTERN void libpd_add_to_search_path(const char *sym); + +EXTERN void *libpd_openfile(const char *basename, const char *dirname); +EXTERN void libpd_closefile(void *p); +EXTERN int libpd_getdollarzero(void *p); + +EXTERN int libpd_blocksize(void); +EXTERN int libpd_init_audio(int inChans, int outChans, int sampleRate); +EXTERN int libpd_process_raw(const float *inBuffer, float *outBuffer); +EXTERN int libpd_process_short(const int ticks, + const short *inBuffer, short *outBuffer); +EXTERN int libpd_process_float(int ticks, + const float *inBuffer, float *outBuffer); +EXTERN int libpd_process_double(int ticks, + const double *inBuffer, double *outBuffer); + +EXTERN int libpd_arraysize(const char *name); +// The parameters of the next two functions are inspired by memcpy. +EXTERN int libpd_read_array(float *dest, const char *src, int offset, int n); +EXTERN int libpd_write_array(const char *dest, int offset, float *src, int n); + +EXTERN int libpd_bang(const char *recv); +EXTERN int libpd_float(const char *recv, float x); +EXTERN int libpd_symbol(const char *recv, const char *sym); + +EXTERN void libpd_set_float(t_atom *v, float x); +EXTERN void libpd_set_symbol(t_atom *v, const char *sym); +EXTERN int libpd_list(const char *recv, int argc, t_atom *argv); +EXTERN int libpd_message(const char *recv, const char *msg, int argc, t_atom *argv); + +EXTERN int libpd_start_message(int max_length); +EXTERN void libpd_add_float(float x); +EXTERN void libpd_add_symbol(const char *sym); +EXTERN int libpd_finish_list(const char *recv); +EXTERN int libpd_finish_message(const char *recv, const char *msg); + +EXTERN int libpd_exists(const char *sym); +EXTERN void *libpd_bind(const char *sym); +EXTERN void libpd_unbind(void *p); + +EXTERN int libpd_is_float(t_atom *a); +EXTERN int libpd_is_symbol(t_atom *a); +EXTERN float libpd_get_float(t_atom *a); +EXTERN char *libpd_get_symbol(t_atom *a); +EXTERN t_atom *libpd_next_atom(t_atom *a); + +typedef void (*t_libpd_printhook)(const char *recv); +typedef void (*t_libpd_banghook)(const char *recv); +typedef void (*t_libpd_floathook)(const char *recv, float x); +typedef void (*t_libpd_symbolhook)(const char *recv, const char *sym); +typedef void (*t_libpd_listhook)(const char *recv, int argc, t_atom *argv); +typedef void (*t_libpd_messagehook)(const char *recv, const char *msg, + int argc, t_atom *argv); + +EXTERN void libpd_set_printhook(const t_libpd_printhook hook); +EXTERN void libpd_set_banghook(const t_libpd_banghook hook); +EXTERN void libpd_set_floathook(const t_libpd_floathook hook); +EXTERN void libpd_set_symbolhook(const t_libpd_symbolhook hook); +EXTERN void libpd_set_listhook(const t_libpd_listhook hook); +EXTERN void libpd_set_messagehook(const t_libpd_messagehook hook); + +EXTERN int libpd_noteon(int channel, int pitch, int velocity); +EXTERN int libpd_controlchange(int channel, int controller, int value); +EXTERN int libpd_programchange(int channel, int value); +EXTERN int libpd_pitchbend(int channel, int value); +EXTERN int libpd_aftertouch(int channel, int value); +EXTERN int libpd_polyaftertouch(int channel, int pitch, int value); +EXTERN int libpd_midibyte(int port, int byte); +EXTERN int libpd_sysex(int port, int byte); +EXTERN int libpd_sysrealtime(int port, int byte); + +typedef void (*t_libpd_noteonhook)(int channel, int pitch, int velocity); +typedef void (*t_libpd_controlchangehook)(int channel, + int controller, int value); +typedef void (*t_libpd_programchangehook)(int channel, int value); +typedef void (*t_libpd_pitchbendhook)(int channel, int value); +typedef void (*t_libpd_aftertouchhook)(int channel, int value); +typedef void (*t_libpd_polyaftertouchhook)(int channel, int pitch, int value); +typedef void (*t_libpd_midibytehook)(int port, int byte); + +EXTERN void libpd_set_noteonhook(const t_libpd_noteonhook hook); +EXTERN void libpd_set_controlchangehook(const t_libpd_controlchangehook hook); +EXTERN void libpd_set_programchangehook(const t_libpd_programchangehook hook); +EXTERN void libpd_set_pitchbendhook(const t_libpd_pitchbendhook hook); +EXTERN void libpd_set_aftertouchhook(const t_libpd_aftertouchhook hook); +EXTERN void libpd_set_polyaftertouchhook(const t_libpd_polyaftertouchhook hook); +EXTERN void libpd_set_midibytehook(const t_libpd_midibytehook hook); +EXTERN void libpd_sys_microsleep(int sleep); +#ifdef __cplusplus +} +#endif + +#endif
--- a/projects/basic_midi/render.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/basic_midi/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -12,6 +12,25 @@ #include <rtdk.h> #include <cmath> +float gFreq; +float gPhaseIncrement = 0; +bool gIsNoteOn = 0; +int gVelocity = 0; +float gSamplingPeriod = 0; + +void midiMessageCallback(MidiChannelMessage message, void* arg){ + if(arg != NULL){ + rt_printf("Message from midi port %d: ", *(int*)arg); + } + message.prettyPrint(); + if(message.getType() == kmmNoteOn){ + gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440; + gVelocity = message.getDataByte(1); + gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod; + gIsNoteOn = gVelocity > 0; + rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity); + } +} // setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. @@ -21,15 +40,18 @@ // // Return true on success; returning false halts the program. Midi midi; +int gMidiPort0 = 0; bool setup(BeagleRTContext *context, void *userData) { - midi.readFrom(0); - midi.writeTo(0); -// midi.enableParser(true); + midi.readFrom(gMidiPort0); + midi.writeTo(gMidiPort0); + midi.enableParser(true); + midi.setParserCallback(midiMessageCallback, &gMidiPort0); if(context->analogFrames == 0) { - rt_printf("Error: this example needs the matrix enabled\n"); + rt_printf("Error: this example needs the analog I/O to be enabled\n"); return false; } + gSamplingPeriod = 1/context->audioSampleRate; return true; } @@ -38,21 +60,18 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -static midi_byte_t noteOnStatus = 0x90; //on channel 1 enum {kVelocity, kNoteOn, kNoteNumber}; void render(BeagleRTContext *context, void *userData) { - static float f0; - static float phaseIncrement = 0; - static bool noteOn = 0; - static int velocity = 0; +// one way of getting the midi data is to parse them yourself +// (you should set midi.enableParser(false) above): +/* + static midi_byte_t noteOnStatus = 0x90; //on channel 1 static int noteNumber = 0; static int waitingFor = kNoteOn; static int playingNote = -1; -/* int message; - // one way of getting the midi data is to parse them yourself (you should set midi.enableParser(false) above): while ((message = midi.getInput()) >= 0){ rt_printf("%d\n", message); switch(waitingFor){ @@ -92,6 +111,7 @@ } } */ + /* int num; //alternatively, you can use the built-in parser (only processes channel messages at the moment). while((num = midi.getParser()->numAvailableMessages()) > 0){ @@ -103,28 +123,31 @@ velocity = message.getDataByte(1); phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate; noteOn = velocity > 0; - rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, velocity); + rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity); } } - + */ + // the following block toggles the LED on an Owl pedal + // and asks the pedal to return the status of the LED + // using MIDI control changes for(unsigned int n = 0; n < context->analogFrames; n++){ static int count = 0; static bool state = 0; analogWriteFrameOnce(context, n, 1, state); if(count % 40000 == 0){ state = !state; - midi_byte_t bytes[6] = {176, 30, state*127, 176, 67, 30}; // toggle the OWL led and ask for the led status + midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status midi.writeOutput(bytes, 6); } count++; } for(unsigned int n = 0; n < context->audioFrames; n++){ - if(noteOn == 1){ + if(gIsNoteOn == 1){ static float phase = 0; - phase += phaseIncrement; + phase += gPhaseIncrement; if(phase > 2 * M_PI) phase -= 2 * M_PI; - float value = sinf(phase) * velocity/128.0f; + float value = sinf(phase) * gVelocity/128.0f; audioWriteFrame(context, n, 0, value); audioWriteFrame(context, n, 1, value); } else {
--- a/projects/basic_network/render.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/basic_network/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -8,42 +8,10 @@ #include <BeagleRT.h> //#include <rtdk.h> #include <cmath> -#include <UdpClient.h> +#include <NetworkSend.h> +#include <ReceiveAudioThread.h> #include <Utilities.h> -AuxiliaryTask transmitReceiveDataTask; - -#define NETWORK_AUDIO_BUFFER_SIZE 400 //1400/4 //maximum payload for a UDP datagram over ethernet is 1472 bytes, I leave some headroom and divide by 4 to get the number of floats -struct networkAudio{ - int timestamp; - int currentBuffer; - int index; - float buffers[2][NETWORK_AUDIO_BUFFER_SIZE]; - int doneOnTime; - bool toBeSent; - UdpClient udpClient; -}; - -float gFrequency; -float gPhase; -float gInverseSampleRate; -int gCount=0; -//networkData networkObject; -#define numNetAudio 3 -networkAudio netAudio[numNetAudio]; -AuxiliaryTask printIntervalTask; -AuxiliaryTask transmitReceiveAudioTask; - -void transmitReceiveAudio(){ //transmit and receive audio buffers - for(int n=0;n<numNetAudio; n++){ - if(netAudio[n].toBeSent){ - netAudio[n].toBeSent=false; - netAudio[n].udpClient.send(netAudio[n].buffers[!netAudio[n].currentBuffer],NETWORK_AUDIO_BUFFER_SIZE*sizeof(float)); - netAudio[n].doneOnTime=1; - } - } -} - // setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. @@ -52,33 +20,22 @@ // in from the call to initAudio(). // // Return true on success; returning false halts the program. + +NetworkSend networkSend; +ReceiveAudioThread receive; +float gFrequency; +float gInverseSampleRate; +float gPhase; bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call gFrequency = *(float *)userData; + networkSend.setup(context->audioSampleRate, context->audioFrames, 0, 9999, "192.168.7.1"); + receive.init(10000, context->audioFrames, 0); + receive.startThread(); gInverseSampleRate = 1.0 / context->audioSampleRate; - gPhase = 0.0; - -// networkObject.counter=&gCount; -// networkObject.variables[0]=&gFrequency; -// networkObject.variables[1]=&gPhase; -// networkObject.numVariables=2; - for(int n=0; n<numNetAudio; n++){ - netAudio[n].doneOnTime=1; - netAudio[n].index=0; - netAudio[n].currentBuffer=0; - netAudio[n].toBeSent=false; -// netAudio[n].udpClient.setPort(settings->transmitPort+n); -// netAudio[n].udpClient.setServer(settings->serverName); - netAudio[n].udpClient.setPort(9999+n); - netAudio[n].udpClient.setServer("192.168.7.1"); - } -// setupSockets(settings->receivePort, settings->transmitPort, settings->serverName); - -// transmitReceiveDataTask=createAuxiliaryTask(*transmitReceiveData, 10, "transmit-receive-data"); -// scheduleAuxiliaryTask(transmitReceiveDataTask); //here it does not work - transmitReceiveAudioTask=BeagleRT_createAuxiliaryTask(*transmitReceiveAudio, 98, "transmit-receive-audio"); + gPhase = 0; return true; } @@ -88,57 +45,19 @@ // will be 0. void render(BeagleRTContext *context, void *userData) -{/* +{ for(unsigned int n = 0; n < context->audioFrames; n++) { float out = 0.7f * sinf(gPhase); gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; if(gPhase > 2.0 * M_PI) gPhase -= 2.0 * M_PI; - for(unsigned int channel = 0; channel < context->audioChannels; channel++) - context->audioOut[n * context->audioChannels + channel] = out; - - if(gCount == 0){ - BeagleRT_scheduleAuxiliaryTask(transmitReceiveDataTask); + networkSend.log(out); + float in; + int ret = receive.getSamplesSrc(&in, 1, 1); + for(unsigned int channel = 0; channel < context->audioChannels; channel++){ + audioWriteFrame(context, n, channel, in); } - gCount++; - } - - -*/ - for(int n = 0; n < context->audioFrames; n++) { - float out = 0.7f * sinf(gPhase); - gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; - if(gPhase > 2.0 * M_PI) - gPhase -= 2.0 * M_PI; - -// for(int channel = 0; channel < context->audioChannels; channel++) -// context->audioOut[n * context->audioChannels + channel] = context->audioIn[n * context->audioChannels + 0]+context->audioIn[n * context->audioChannels + 1]; - context->audioOut[n * context->audioChannels] = context->audioIn[n*context->audioChannels+0]; - context->audioOut[n * context->audioChannels+1]=out; - if(0==gCount){ -// scheduleAuxiliaryTask(transmitReceiveDataTask); - } - for(int j=0; j<numNetAudio; j++){ - if(netAudio[j].index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ... - netAudio[j].toBeSent=true; - netAudio[j].index=0; //reset the counter - if(netAudio[j].doneOnTime==0) - rt_printf("Network buffer underrun :-{\n"); - netAudio[j].timestamp=gCount; - netAudio[j].currentBuffer=!netAudio[j].currentBuffer; //switch buffer - netAudio[j].doneOnTime=0; - BeagleRT_scheduleAuxiliaryTask(transmitReceiveAudioTask); //send the buffer - } - } - if((gCount&1)==0){ - netAudio[1].buffers[netAudio[1].currentBuffer][netAudio[1].index++]=analogReadFrame(context,n/2,0)+context->audioOut[n*context->audioChannels + 0]; - netAudio[2].buffers[netAudio[2].currentBuffer][netAudio[2].index++]=analogReadFrame(context,n/2,1)+context->audioOut[n*context->audioChannels + 0]; - } - netAudio[0].buffers[netAudio[0].currentBuffer][netAudio[0].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]);//copy channel 0 to the buffer -// netAudio[1].buffers[netAudio[1].currentBuffer][netAudio[1].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]); -// netAudio[2].buffers[netAudio[2].currentBuffer][netAudio[2].index++]=0.5*(out+context->audioOut[n*context->audioChannels + 0]); - gCount++; } }
--- a/projects/d-box/logger.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/d-box/logger.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -8,7 +8,7 @@ #include "logger.h" // main extern vars -extern bool gShouldStop; +extern int gShouldStop; extern int gVerbose; // file nanme extern vars
--- a/projects/d-box/sensors.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/d-box/sensors.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -22,7 +22,7 @@ extern vector<OscillatorBank*> gOscBanks; extern int gCurrentOscBank; extern int gNextOscBank; -extern bool gShouldStop; +extern int gShouldStop; extern int gVerbose; float gSensor0LatestTouchPos = 0; // most recent pitch touch location [0-1] on sensor 0, used by render.cpp
--- a/projects/heavy/pd/hello-midi/_main.pd Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/heavy/pd/hello-midi/_main.pd Sun Apr 10 04:08:06 2016 +0200 @@ -1,4 +1,4 @@ -#N canvas 94 174 1280 685 10; +#N canvas 85 58 1280 685 10; #X obj 19 396 dac~ 1 2; #X text 39 1 Hello world!; #X text 37 11 ============; @@ -7,11 +7,9 @@ #X text 202 438 @krighxz / BELA / heavy / 12/2015; #X text 226 457 beaglert.cc / enzienaudio.com; #X obj 39 132 mtof; -#X text 140 29 <== the heavy equivalent of ==>; -#X obj 334 24 notein; -#X floatatom 79 59 5 0 0 0 - - -, f 5; -#X floatatom 122 59 5 0 0 0 - - -, f 5; -#X floatatom 41 63 5 0 0 0 - - -, f 5; +#X floatatom 79 59 5 0 0 0 - - -; +#X floatatom 122 59 5 0 0 0 - - -; +#X floatatom 41 63 5 0 0 0 - - -; #X obj 26 170 phasor~ 440; #X text 100 363 (the harsh sound of success); #X obj 260 83 * 20; @@ -19,18 +17,12 @@ #X obj 132 85 loadbang; #X msg 131 111 1000; #X obj 125 166 sig~; -#X text 483 121 <== the heavy equivalent of ==>; -#X text 349 57 <== the heavy equivalent of ==>; -#X text 682 122 [pgmin]; +#X text 673 121 [pgmin]; #X obj 218 178 * 10; #X obj 30 250 hip~; #X obj 26 275 hip~; #X obj 20 302 hip~; #X obj 19 323 hip~; -#X obj 40 28 hv_notein 0; -#X obj 408 122 hv_pgmin 3; -#X obj 260 60 hv_ctlin 5 0; -#X obj 220 151 hv_ctlin 6 0; #X obj 87 192 lop~ 4; #X obj 152 256 line; #X obj 200 200 + 50; @@ -38,43 +30,50 @@ #X msg 93 114 0; #X msg 185 112 0; #X obj 29 224 vcf~ 4; -#X obj 557 54 ctlin 5 0; -#X obj 323 156 ctlin 6 0; #X obj 70 333 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 42 92 mono; +#X obj 40 28 bela_notein 0; +#X obj 260 60 bela_ctlin 5 0; +#X obj 220 151 bela_ctlin 6 0; +#X obj 408 121 bela_pgmin 3; +#X text 537 58 [ctlin]; +#X text 332 27 [notein]; +#X text 140 29 <== the bela equivalent of ==>; +#X text 349 59 <== the bela equivalent of ==>; +#X text 483 121 <== the bela equivalent of ==>; #X connect 3 0 0 1; #X connect 3 0 0 0; -#X connect 7 0 13 0; -#X connect 10 0 42 1; -#X connect 12 0 42 0; -#X connect 13 0 38 0; +#X connect 7 0 11 0; +#X connect 8 0 32 1; +#X connect 10 0 32 0; +#X connect 11 0 30 0; +#X connect 13 0 14 0; +#X connect 14 0 17 0; #X connect 15 0 16 0; -#X connect 16 0 19 0; -#X connect 17 0 18 0; -#X connect 17 0 37 0; -#X connect 17 0 36 0; -#X connect 18 0 19 0; -#X connect 19 0 32 0; -#X connect 23 0 34 0; -#X connect 24 0 25 0; -#X connect 25 0 26 0; +#X connect 15 0 29 0; +#X connect 15 0 28 0; +#X connect 16 0 17 0; +#X connect 17 0 24 0; +#X connect 19 0 26 0; +#X connect 20 0 21 0; +#X connect 21 0 22 0; +#X connect 22 0 23 0; +#X connect 23 0 3 0; +#X connect 24 0 30 1; +#X connect 25 0 20 1; +#X connect 25 0 21 1; +#X connect 25 0 22 1; +#X connect 25 0 23 1; #X connect 26 0 27 0; -#X connect 27 0 3 0; -#X connect 28 0 12 0; -#X connect 28 1 10 0; -#X connect 28 2 11 0; -#X connect 30 0 15 0; -#X connect 31 0 23 0; -#X connect 32 0 38 1; -#X connect 33 0 24 1; -#X connect 33 0 25 1; -#X connect 33 0 26 1; -#X connect 33 0 27 1; -#X connect 34 0 35 0; -#X connect 35 0 33 0; -#X connect 37 0 23 0; -#X connect 38 0 24 0; -#X connect 41 0 3 1; -#X connect 42 0 7 0; -#X connect 42 1 41 0; +#X connect 27 0 25 0; +#X connect 29 0 19 0; +#X connect 30 0 20 0; +#X connect 31 0 3 1; +#X connect 32 0 7 0; +#X connect 32 1 31 0; +#X connect 33 0 10 0; +#X connect 33 1 8 0; +#X connect 33 2 9 0; +#X connect 34 0 13 0; +#X connect 35 0 19 0;
--- a/projects/heavy/pd/hello-midi/countTo.pd Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/heavy/pd/hello-midi/countTo.pd Sun Apr 10 04:08:06 2016 +0200 @@ -1,4 +1,4 @@ -#N canvas 586 250 450 300 10; +#N canvas 584 255 450 300 10; #X obj 65 196 outlet; #X obj 98 8 inlet; #X text 189 49 counts from 0 to the given number -1; @@ -7,13 +7,12 @@ #X obj 143 61 f; #X obj 100 138 spigot; #X obj 129 89 <; -#X obj 129 113 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 +#X obj 129 113 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 95 28 t b f b; #X obj 92 74 + 1; -#X obj 43 73 f, f 4; +#X obj 43 73 f; #X obj 63 104 t b f f f; -#X obj 143 155 spigot; #X msg 92 53 0; #X obj 16 144 delay 0; #X connect 1 0 9 0; @@ -23,12 +22,12 @@ #X connect 8 0 6 1; #X connect 9 0 11 0; #X connect 9 1 5 0; -#X connect 9 1 14 0; +#X connect 9 1 13 0; #X connect 10 0 11 1; #X connect 11 0 12 0; -#X connect 12 0 15 0; +#X connect 12 0 14 0; #X connect 12 1 0 0; #X connect 12 2 7 0; #X connect 12 3 10 0; -#X connect 14 0 11 1; -#X connect 15 0 6 0; +#X connect 13 0 11 1; +#X connect 14 0 6 0;
--- a/projects/heavy/pd/hello-midi/hv_ctlin.pd Sat Feb 13 01:51:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -#N canvas 554 204 703 475 10; -#X obj -107 -439 outlet; -#X obj -52 -441 outlet; -#X obj -61 -743 r ctlin; -#X obj -68 -719 unpack f f f; -#X obj -6 -441 outlet; -#X obj -74 -548 spigot; -#X text -109 -420 value; -#X text -55 -420 number; -#X obj 51 -732 loadbang; -#X obj 17 -677 \$1; -#X obj -34 -656 == \$1; -#X obj -41 -571 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 -0 1; -#X obj -76 -521 unpack f f f; -#X obj -17 -623 ||; -#X obj 17 -653 == 0; -#X text -90 -859 Emulates ctlin \, except number of outlets is fixed. -; -#X obj 68 -623 ||; -#X obj 102 -653 == 0; -#X obj 52 -656 == \$2; -#X obj 102 -677 \$2; -#X obj 17 -593 &&; -#X obj 51 -707 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X text 13 -571 If (inputController==\$1 || \$1==0) && (inputChannel==\$2 -|| \$2==0); -#X text 37 -818 Known issue: trying to select inputController 0 will -result i accepting all controllers (because a pd external cannot tell -the difference between \$1 been explicitely set to 0 and the patch -not having any argument); -#X text 2 -420 channel; -#X obj -104 -678 pack f f f; -#X obj -80 -462 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom -79 -488 5 0 0 0 - - -; -#X obj -39 -458 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom -38 -484 5 0 0 0 - - -; -#X obj 12 -464 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom 13 -490 5 0 0 0 - - -; -#X msg -44 -818 1 2 3; -#X msg -6 -805 1 5 7; -#X msg -97 -815 1 5 6; -#X msg -100 -776 1 4 7; -#X obj -96 -841 r hv_ctlin; -#X obj -38 -778 s ctlin; -#X connect 2 0 3 0; -#X connect 3 0 25 0; -#X connect 3 1 10 0; -#X connect 3 1 25 1; -#X connect 3 2 18 0; -#X connect 3 2 25 2; -#X connect 5 0 12 0; -#X connect 8 0 21 0; -#X connect 9 0 14 0; -#X connect 10 0 13 0; -#X connect 11 0 5 1; -#X connect 12 0 0 0; -#X connect 12 0 27 0; -#X connect 12 1 1 0; -#X connect 12 1 29 0; -#X connect 12 2 4 0; -#X connect 12 2 31 0; -#X connect 13 0 20 0; -#X connect 14 0 13 1; -#X connect 16 0 20 1; -#X connect 17 0 16 1; -#X connect 18 0 16 0; -#X connect 19 0 17 0; -#X connect 20 0 11 0; -#X connect 21 0 9 0; -#X connect 21 0 19 0; -#X connect 25 0 5 0; -#X connect 27 0 26 0; -#X connect 29 0 28 0; -#X connect 31 0 30 0; -#X connect 32 0 37 0; -#X connect 33 0 37 0; -#X connect 34 0 37 0; -#X connect 35 0 37 0; -#X connect 36 0 37 0;
--- a/projects/heavy/pd/hello-midi/hv_notein.pd Sat Feb 13 01:51:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -#N canvas 730 58 629 685 10; -#X obj 84 -361 outlet; -#X obj 155 -367 outlet; -#X obj 131 -658 unpack f f f; -#X obj 211 -370 outlet; -#X obj 133 -477 spigot; -#X obj 258 -661 loadbang; -#X obj 224 -606 \$1; -#X obj 173 -585 == \$1; -#X obj 166 -500 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 -0 1; -#X obj 133 -450 unpack f f f; -#X obj 190 -552 ||; -#X obj 224 -582 == 0; -#X obj 258 -636 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X text 150 -777 Emulates notein \, except number of outlets is fixed. -; -#X text 82 -343 notenumber; -#X text 151 -353 velocity; -#X text 210 -356 channel; -#X text 219 -531 If (inputChannel==\$1 || \$1==0); -#X msg 50 -758 123 46 3; -#X obj 105 -610 pack f f f; -#X msg 8 -739 123 46 2; -#X obj 72 -414 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom 74 -432 5 0 0 0 - - -; -#X obj 135 -394 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom 137 -412 5 0 0 0 - - -; -#X obj 188 -391 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X floatatom 190 -409 5 0 0 0 - - -; -#X obj 121 -730 s notein; -#X obj 130 -693 r notein; -#X obj 125 -758 r hv_notein; -#X connect 2 0 19 0; -#X connect 2 1 19 1; -#X connect 2 2 7 0; -#X connect 2 2 19 2; -#X connect 4 0 9 0; -#X connect 5 0 12 0; -#X connect 6 0 11 0; -#X connect 7 0 10 0; -#X connect 8 0 4 1; -#X connect 9 0 0 0; -#X connect 9 0 22 0; -#X connect 9 1 1 0; -#X connect 9 1 24 0; -#X connect 9 2 3 0; -#X connect 9 2 26 0; -#X connect 10 0 8 0; -#X connect 11 0 10 1; -#X connect 12 0 6 0; -#X connect 18 0 27 0; -#X connect 19 0 4 0; -#X connect 20 0 27 0; -#X connect 22 0 21 0; -#X connect 24 0 23 0; -#X connect 26 0 25 0; -#X connect 28 0 2 0; -#X connect 29 0 27 0;
--- a/projects/heavy/pd/hello-midi/hv_pgmin.pd Sat Feb 13 01:51:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -#N canvas 623 197 587 546 10; -#X obj 108 68 outlet; -#X obj 209 66 outlet; -#X obj 141 -41 spigot; -#X obj 232 -219 loadbang; -#X obj 232 -170 \$1; -#X obj 181 -149 == \$1; -#X obj 174 -64 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 -1; -#X obj 198 -116 ||; -#X obj 232 -146 == 0; -#X obj 232 -194 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 --1 -1; -#X obj 124 -234 unpack f f; -#X obj 141 -13 unpack f f; -#X text 87 91 program number; -#X text 217 87 channel; -#X text 228 -64 If (channel==\$1 || \$1==0); -#X text 202 -300 emulates pgmin except it always has 2 outlets and -requires the input parameters to be explicitely set. Set them to 0 -to avoid filtering; -#X text 297 -213 It'd be nicer with [t l l] but have to compensate -for the fact that it is not supported by heavy; -#X obj 112 -162 pack f f; -#X floatatom 107 10 5 0 0 0 - - -; -#X msg 80 -270 2 3; -#X msg 63 -292 2 1; -#X obj 98 34 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 --1; -#X floatatom 185 16 5 0 0 0 - - -; -#X obj 176 40 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 --1; -#X obj 124 -303 r hv_pgmin; -#X obj 126 -282 s pgmin; -#X obj 128 -258 r pgmin; -#X connect 2 0 11 0; -#X connect 3 0 9 0; -#X connect 4 0 8 0; -#X connect 5 0 7 0; -#X connect 6 0 2 1; -#X connect 7 0 6 0; -#X connect 8 0 7 1; -#X connect 9 0 4 0; -#X connect 10 0 17 0; -#X connect 10 1 5 0; -#X connect 10 1 17 1; -#X connect 11 0 0 0; -#X connect 11 0 18 0; -#X connect 11 1 1 0; -#X connect 11 1 22 0; -#X connect 17 0 2 0; -#X connect 18 0 21 0; -#X connect 19 0 25 0; -#X connect 20 0 25 0; -#X connect 22 0 23 0; -#X connect 24 0 25 0; -#X connect 26 0 10 0;
--- a/projects/scope/render.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/projects/scope/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -1,12 +1,14 @@ #include <BeagleRT.h> -#include <Scope.h> +#include <NetworkSend.h> +#include <ReceiveAudioThread.h> #include <cmath> float gPhase1, gPhase2; float gFrequency1, gFrequency2; float gInverseSampleRate; -Scope scope; //create a scope object +Scope scope(2); //create a scope object with 2 channels +NetworkSend networkSend; // initialise_render() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent @@ -16,9 +18,17 @@ // in from the call to initAudio(). // // Return true on success; returning false halts the program. +ReceiveAudioThread receiveAudio0; +ReceiveAudioThread receiveAudio1; bool setup(BeagleRTContext *context, void *userData) { - scope.setup(context->audioSampleRate); //call this once in setup to initialise the scope + receiveAudio0.init(9999, context->audioFrames, 0); + receiveAudio1.init(10000, context->audioFrames, 1); + + scope.setup(); //call this once in setup to initialise the scope + scope.setPort(0, 9999); + scope.setPort(1, 10000); +// networkSend.setup(context->audioSampleRate, 0, 9999, "192.168.7.1"); gInverseSampleRate = 1.0/context->audioSampleRate; @@ -27,6 +37,7 @@ gFrequency1 = 200.0; gFrequency2 = 201.0; + return true; } @@ -37,33 +48,48 @@ void render(BeagleRTContext *context, void *userData) { + static int count=0; + if(count==0){ + printf("startHread\n"); + ReceiveAudioThread::startThread(); + } for(unsigned int n = 0; n < context->audioFrames; n++) { - float chn1 = sinf(gPhase1); - float chn2 = sinf(gPhase2); - - float chn3 = context->audioIn[n*2 + 0]; - float chn4 = context->audioIn[n*2 + 1]; - - float chn5 = context->analogIn[(int)n/2*8 + 0]; - float chn6 = context->analogIn[(int)n/2*8 + 1]; + float chn0 = sinf(gPhase1); + float chn1 = sinf(gPhase2); + + // float chn2 = context->audioIn[n*2 + 0]; + // float chn3 = context->audioIn[n*2 + 1]; + + // float chn4 = context->analogIn[(int)n/2*8 + 0]; + // float chn5 = context->analogIn[(int)n/2*8 + 1]; + scope.log(0, chn0); + scope.log(1, chn1); + // scope.log(2, chn2); + // scope.log(3, chn3); + // scope.log(4, chn4); + // scope.log(5, chn5); // scope.log(chn1, chn2, chn3, chn4, chn5, chn6); - scope.log(chn1); //call this once every audio frame //takes six or fewer floats as parameters //first parameter becomes channel 1 etc //to view, click the 'oscilloscope' button on the toolbar while BeagleRT is NOT running //then click the big red button on the toolbar on this page - gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate; - gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate; + gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate * ((count&4095)/4096.0+1); + gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate; if(gPhase1 > 2.0 * M_PI) gPhase1 -= 2.0 * M_PI; if(gPhase2 > 2.0 * M_PI) gPhase2 -= 2.0 * M_PI; } + if(count>0){ + int readPointer0=receiveAudio0.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 0); + int readPointer1=receiveAudio1.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 1); + } + count++; } // cleanup_render() is called once at the end, after the audio has stopped.
--- a/scripts/hvresources/render.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/scripts/hvresources/render.cpp Sun Apr 10 04:08:06 2016 +0200 @@ -127,16 +127,16 @@ float velocity = message.getDataByte(1); float channel = message.getChannel(); // rt_printf("message: noteNumber: %f, velocity: %f, channel: %f\n", noteNumber, velocity, channel); - hv_vscheduleMessageForReceiver(gHeavyContext, "hv_notein", 0, "fff", noteNumber, velocity, channel); + hv_vscheduleMessageForReceiver(gHeavyContext, "bela_notein", 0, "fff", noteNumber, velocity, channel); } break; case kmmControlChange: { - hv_vscheduleMessageForReceiver(gHeavyContext, "hv_ctlin", 0, "fff", + hv_vscheduleMessageForReceiver(gHeavyContext, "bela_ctlin", 0, "fff", (float)message.getDataByte(1), (float)message.getDataByte(0), (float)message.getChannel()); } break; case kmmProgramChange: - hv_vscheduleMessageForReceiver(gHeavyContext, "hv_pgmin", 0, "ff", + hv_vscheduleMessageForReceiver(gHeavyContext, "bela_pgmin", 0, "ff", (float)message.getDataByte(0), (float)message.getChannel()); break; }
--- a/scripts/hvresources/uploader.py Sat Feb 13 01:51:01 2016 +0000 +++ b/scripts/hvresources/uploader.py Sun Apr 10 04:08:06 2016 +0200 @@ -1,6 +1,4 @@ -#!/usr/bin/python - -# Copyright 2015 Section6. All Rights Reserved. +# Copyright 2015,2016 Enzien Audio, Ltd. All Rights Reserved. import argparse import getpass @@ -13,7 +11,6 @@ import time import urlparse import zipfile -import sys class Colours: purple = "\033[95m" @@ -47,19 +44,27 @@ description="Compiles a Pure Data file.") parser.add_argument( "input_dir", - help="A directory containing _main.pd. The entire directory will be uploaded.") + help="A directory containing _main.pd. All .pd files in the directory structure will be uploaded.") parser.add_argument( "-n", "--name", default="heavy", - help="Patch name. If it doesn't exist, the uploader will fail. Make sure that it exists on the Heavy website.") + help="Patch name. If it doesn't exist on the Heavy site, the uploader will fail.") parser.add_argument( "-g", "--gen", nargs="+", default=["c"], - help="List of generator outputs. Currently supported generators are 'c' and 'js'.") + help="List of generator outputs. Currently supported generators are " + "'c', 'js', 'pdext', 'pdext-osx', 'unity', 'unity-osx', " + "'unity-win-x86', 'unity-win-x86_64', 'wwise', 'wwise-win-x86_64', " + "'vst2' ,'vst2-osx', and 'vst2-win-x86_64'.") parser.add_argument( "-b", - help="All files will be placed in the output directory, placed in their own subdirectory corresonding to the generator name.", + help="All files will be placed in the output directory, placed in their own subdirectory corresponding to the generator name.", + action="count") + parser.add_argument( + "-y", + help="Extract only the generated C files. Static files are deleted. " + "Only effective for the 'c' generator.", action="count") parser.add_argument( "-o", "--out", @@ -80,12 +85,16 @@ action="count") parser.add_argument( "--noverify", - help="Don't verify the SSL connection. Generally a bad idea.", + help="Don't verify the SSL connection. This is generally a very bad idea.", action="count") parser.add_argument( "-v", "--verbose", help="Show debugging information.", action="count") + parser.add_argument( + "-t", "--token", + help="Use the specified token.", + ) args = parser.parse_args() domain = args.domain or "https://enzienaudio.com" @@ -94,11 +103,14 @@ # token should be stored in ~/.heavy/token token_path = os.path.expanduser(os.path.join("~/", ".heavy", "token")) - if os.path.exists(token_path) and not args.z: + + if args.token is not None: + # check if token has been passed as a command line arg... + post_data["credentials"] = {"token": args.token} + elif os.path.exists(token_path) and not args.z: + # ...or if it is stored in the user's home directory with open(token_path, "r") as f: - post_data["credentials"] = { - "token": f.read() - } + post_data["credentials"] = {"token": f.read()} else: # otherwise, get the username and password post_data["credentials"] = { @@ -127,7 +139,13 @@ post_data["name"] = args.name # the outputs to generate (always include c) - __SUPPORTED_GENERATOR_SET = {"c", "js"} + __SUPPORTED_GENERATOR_SET = { + "c", "js", + "pdext", "pdext-osx", + "unity", "unity-osx", "unity-win-x86", "unity-win-x86_64", + "wwise", "wwise-win-x86_64", + "vst2", "vst2-osx", "vst2-win-x86_64", + } post_data["gen"] = list(({"c"} | set(args.gen)) & __SUPPORTED_GENERATOR_SET) # upload the job, get the response back @@ -141,6 +159,7 @@ if r.status_code != requests.codes.ok: shutil.rmtree(temp_dir) # clean up the temporary directory + print "Getting a weird error? Get the latest uploader at https://enzienaudio.com/static/uploader.py" r.raise_for_status() # raise an exception # decode the JSON API response @@ -193,7 +212,9 @@ "type": "file" } ], - "warnings": [], + "warnings": [ + {"details": "blah blah blah"} + ], "meta": { "token": "11AS0qPRmjTUHEMSovPEvzjodnzB1xaz" } @@ -209,22 +230,32 @@ # update the api token, if present if "token" in reply_json.get("meta",{}) and not args.x: - if not os.path.exists(os.path.dirname(token_path)): - os.makedirs(os.path.dirname(token_path)) # ensure that the .heavy directory exists - with open(token_path, "w") as f: - f.write(reply_json["meta"]["token"]) - os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) # force rw------- permissions on the file + if args.token is not None: + if reply_json["meta"]["token"] != args.token: + print "WARNING: Token returned by API is not the same as the " + "token supplied at the command line. (old = %s, new = %s)".format( + args.token, + reply_json["meta"]["token"]) + else: + if not os.path.exists(os.path.dirname(token_path)): + # ensure that the .heavy directory exists + os.makedirs(os.path.dirname(token_path)) + with open(token_path, "w") as f: + f.write(reply_json["meta"]["token"]) + # force rw------- permissions on the file + os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) # print any warnings - for x in r_json["warnings"]: - print "{0}Warning:{1} {2}".format(Colours.yellow, Colours.end, x["detail"]) + for i,x in enumerate(r_json.get("warnings",[])): + print "{3}) {0}Warning:{1} {2}".format( + Colours.yellow, Colours.end, x["detail"], i+1) # check for errors if len(r_json.get("errors",[])) > 0: shutil.rmtree(temp_dir) # clean up the temporary directory - for x in r_json["errors"]: - print "{0}Error:{1} {2}".format(Colours.red, Colours.end, x["detail"]) - sys.exit(1) + for i,x in enumerate(r_json["errors"]): + print "{3}) {0}Error:{1} {2}".format( + Colours.red, Colours.end, x["detail"], i+1) return # retrieve all requested files @@ -251,6 +282,12 @@ os.makedirs(target_dir) # ensure that the output directory exists __unzip(c_zip_path, target_dir) + if g == "c" and args.y: + keep_files = ("_{0}.h".format(args.name), "_{0}.c".format(args.name)) + for f in os.listdir(target_dir): + if not f.endswith(keep_files): + os.remove(os.path.join(target_dir, f)); + print "{0} files placed in {1}".format(g, target_dir) else: print "{0}Warning:{1} {2} files could not be retrieved.".format( @@ -260,10 +297,9 @@ # delete the temporary directory shutil.rmtree(temp_dir) - print "Job URL", reply_json["data"]["links"]["self"] + print "Job URL:", reply_json["data"]["links"]["self"] print "Total request time: {0}ms".format(int(1000.0*(time.time()-tick))) - - sys.exit(0) + print "Heavy version:", reply_json["meta"]["version"] def __get_file_url_for_generator(json_api, g): """Returns the file link for a specific generator.