Mercurial > hg > beaglert
changeset 50:be427da6fb9c newapi
Removed old testing code that stopped audio after 10 seconds; command line parameter updates; D-Box updates (not fully working yet)
author | andrewm |
---|---|
date | Sat, 30 May 2015 12:34:32 -0500 |
parents | bb40e7e06b8c |
children | 4f8db16f17b5 |
files | .cproject core/PRU.cpp core/RTAudio.cpp core/RTAudioCommandLine.cpp projects/d-box/FeedbackOscillator.cpp projects/d-box/FeedbackOscillator.h projects/d-box/main.cpp projects/d-box/render.cpp |
diffstat | 8 files changed, 159 insertions(+), 145 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Thu May 28 17:48:42 2015 -0400 +++ b/.cproject Sat May 30 12:34:32 2015 -0500 @@ -92,7 +92,7 @@ <sourceEntries> <entry excluding="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/basic"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/d-box"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration> @@ -167,6 +167,7 @@ <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.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}""/> </option> <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1607203279" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> @@ -181,7 +182,7 @@ <sourceEntries> <entry excluding="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/basic"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/d-box"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration>
--- a/core/PRU.cpp Thu May 28 17:48:42 2015 -0400 +++ b/core/PRU.cpp Sat May 30 12:34:32 2015 -0500 @@ -420,10 +420,13 @@ // Main loop to read and write data from/to PRU void PRU::loop(RT_INTR *pru_interrupt, void *userData) { +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period +#else // Polling interval is 1/4 of the period - //RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; + RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; +#endif - RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period float *lastAnalogOutFrame; uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer; uint32_t pru_audio_offset, pru_spi_offset; @@ -468,10 +471,16 @@ } // TESTING - uint32_t testCount = 0; + // uint32_t testCount = 0; // RTIME startTime = rt_timer_read(); +#ifndef BEAGLERT_USE_XENOMAI_INTERRUPTS + // Which buffer the PRU was last processing + uint32_t lastPRUBuffer = 0; +#endif + while(!gShouldStop) { +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS // Wait for PRU to move to change buffers; // PRU will send an interrupts which we wait for rt_intr_enable(pru_interrupt); @@ -489,6 +498,14 @@ // Clear pending PRU interrupt prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT); +#else + // Poll + while(pru_buffer_comm[PRU_CURRENT_BUFFER] == lastPRUBuffer && !gShouldStop) { + rt_task_sleep(sleepTime); + } + + lastPRUBuffer = pru_buffer_comm[PRU_CURRENT_BUFFER]; +#endif if(gShouldStop) break; @@ -512,7 +529,7 @@ // FIXME: some sort of margin is needed here to prevent the audio // code from completely eating the Linux system - testCount++; + // testCount++; //rt_task_sleep(sleepTime*4); //rt_task_sleep(sleepTime/4); @@ -605,12 +622,14 @@ } // FIXME: TESTING!! - if(testCount > 100000) - break; + // if(testCount > 100000) + // break; } +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS // Turn off the interrupt for the PRU if it isn't already off rt_intr_disable(pru_interrupt); +#endif // FIXME: TESTING // RTIME endTime = rt_timer_read();
--- a/core/RTAudio.cpp Thu May 28 17:48:42 2015 -0400 +++ b/core/RTAudio.cpp Sat May 30 12:34:32 2015 -0500 @@ -52,7 +52,9 @@ // Real-time tasks and objects RT_TASK gRTAudioThread; +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS RT_INTR gRTAudioInterrupt; +#endif PRU *gPRU = 0; I2c_Codec *gAudioCodec = 0; @@ -257,8 +259,11 @@ } } +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS gPRU->loop(&gRTAudioInterrupt, gUserData); - +#else + gPRU->loop(0, gUserData); +#endif // Now clean up // gPRU->waitForFinish(); gPRU->disable(); @@ -341,12 +346,14 @@ return -1; } +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS // Create an interrupt which the audio thread receives from the PRU int result = 0; if((result = rt_intr_create(&gRTAudioInterrupt, gRTAudioInterruptName, PRU_RTAUDIO_IRQ, I_NOAUTOENA)) != 0) { cout << "Error: unable to create Xenomai interrupt for PRU (error " << result << ")" << endl; return -1; } +#endif // Start all RT threads if(rt_task_start(&gRTAudioThread, &audioLoop, 0)) { @@ -413,7 +420,9 @@ gAuxTasks.clear(); // Delete the audio task and its interrupt +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS rt_intr_delete(&gRTAudioInterrupt); +#endif rt_task_delete(&gRTAudioThread); if(gPRU != 0)
--- a/core/RTAudioCommandLine.cpp Thu May 28 17:48:42 2015 -0400 +++ b/core/RTAudioCommandLine.cpp Sat May 30 12:34:32 2015 -0500 @@ -24,22 +24,22 @@ { {"period", 1, NULL, 'p'}, {"verbose", 0, NULL, 'v'}, - {"use-analog", 1, NULL, 'm'}, - {"use-digital-gpio", 1, NULL, 'g'}, + {"use-analog", 1, NULL, 'N'}, + {"use-digital", 1, NULL, 'G'}, {"analog-channels", 1, NULL, 'C'}, - {"digital-channels", 1, NULL, 'G'}, + {"digital-channels", 1, NULL, 'B'}, {"mute-speaker", 1, NULL, 'M'}, {"dac-level", 1, NULL, 'D'}, {"adc-level", 1, NULL, 'A'}, {"hp-level", 1, NULL, 'H'}, - {"receive-port", 1, NULL, 'r'}, - {"transmit-port", 1, NULL, 't'}, - {"server-name", 1, NULL, 's'}, + {"receive-port", 1, NULL, 'R'}, + {"transmit-port", 1, NULL, 'T'}, + {"server-name", 1, NULL, 'S'}, {"pru-file", 1, NULL, OPT_PRU_FILE}, {NULL, 0, NULL, 0} }; -const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:g:G:r:t:s:"; +const char gDefaultShortOptions[] = "p:vN:M:C:D:A:H:G:B:R:T:S:"; // This function sets the default settings for the BeagleRTInitSettings structure void BeagleRT_defaultSettings(BeagleRTInitSettings *settings) @@ -150,10 +150,10 @@ case 'v': settings->verbose = 1; break; - case 'm': + case 'N': settings->useAnalog = atoi(optarg); break; - case 'g': + case 'G': settings->useDigital = atoi(optarg); settings->numDigitalChannels = 0; break; @@ -166,7 +166,7 @@ else settings->numAnalogChannels = 2; break; - case 'G': + case 'B': settings->numDigitalChannels = atoi(optarg); if(settings->numDigitalChannels >= 16) settings->numDigitalChannels = 16; @@ -188,13 +188,13 @@ case 'H': settings->headphoneLevel = atof(optarg); break; - case 'r': + case 'R': settings->receivePort = atoi(optarg); break; - case 't': + case 'T': settings->transmitPort = atoi(optarg); break; - case 's': + case 'S': if(strlen(optarg)<MAX_SERVERNAME_LENGTH) strcpy(settings->serverName, optarg); else
--- a/projects/d-box/FeedbackOscillator.cpp Thu May 28 17:48:42 2015 -0400 +++ b/projects/d-box/FeedbackOscillator.cpp Sat May 30 12:34:32 2015 -0500 @@ -58,23 +58,11 @@ // Process one sample and store the output value // Returns true if the wavetable needs rendering -int FeedbackOscillator::process(uint16_t input, uint16_t *output) { - float inFloat = input / 65536.0; - float outFloat = coeffs[COEFF_B0] * inFloat + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput; +int FeedbackOscillator::process(float input, float *output) { + float outFloat = coeffs[COEFF_B0] * input + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput; int requestRenderLength = 0; - //outFloat *= 2.0; - - int intOut = outFloat * 65536.0 + 32768; - if(intOut > 65535) - intOut = 65535; - if(intOut < 0) - intOut = 0; - //intOut = (intOut & 0xFF) << 8; - //if(intOut > 65535) - // intOut = 65535; - - *output = (uint16_t)intOut; + *output = outFloat; if(canTrigger && outFloat > 0 && lastOutput <= 0) { triggered = true; @@ -106,7 +94,7 @@ sampleCount++; lastOutput = outFloat; - lastInput = inFloat; + lastInput = input; return requestRenderLength; }
--- a/projects/d-box/FeedbackOscillator.h Thu May 28 17:48:42 2015 -0400 +++ b/projects/d-box/FeedbackOscillator.h Sat May 30 12:34:32 2015 -0500 @@ -8,8 +8,6 @@ #ifndef FEEDBACKOSCILLATOR_H #define FEEDBACKOSCILLATOR_H -#include <stdint.h> - class FeedbackOscillator { public: @@ -21,7 +19,7 @@ // Process one sample and store the output value // Returns the length of table to interpolate; or 0 if nothing to process further - int process(uint16_t input, uint16_t *output); + int process(float input, float *output); float *wavetable() { return wavetableRead; }
--- a/projects/d-box/main.cpp Thu May 28 17:48:42 2015 -0400 +++ b/projects/d-box/main.cpp Sat May 30 12:34:32 2015 -0500 @@ -33,7 +33,7 @@ // get_opt_long #include <getopt.h> -#include "../../include/RTAudio.h" +#include "../../include/BeagleRT.h" #include "config.h" #include "sensors.h" #include "OscillatorBank.h" @@ -262,11 +262,13 @@ } -void parseArguments(arg_data args, RTAudioSettings *settings) +void parseArguments(arg_data args, BeagleRTInitSettings *settings) { // Default filename; gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt"); + const int kOptionAudioTest = 1000; + // TODO: complete this struct option long_option[] = { @@ -274,10 +276,10 @@ {"audioin", 1, NULL, 'i'}, {"file", 1, NULL, 'f'}, {"keyboard", 1, NULL, 'k'}, - {"audio-test", 0, NULL, 'T'}, - {"sensor-type", 1, NULL, 'S'}, - {"sensor0", 1, NULL, 'Q'}, - {"sensor1", 1, NULL, 'R'}, + {"audio-test", 0, NULL, kOptionAudioTest}, + {"sensor-type", 1, NULL, 't'}, + {"sensor0", 1, NULL, 'q'}, + {"sensor1", 1, NULL, 'r'}, {"log", 1, NULL, 'l'}, {"usesd", 1, NULL, 'u'}, {"oversamp", 1, NULL, 'o'}, @@ -293,7 +295,7 @@ while (1) { int c; - if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sTQ:R:S:l:u:o:n:g:", long_option, settings)) < 0) + if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0) break; switch (c) { @@ -313,16 +315,16 @@ case 's': forceSensors = true; break; - case 'T': + case kOptionAudioTest: useAudioTest = true; break; - case 'S': + case 't': sensorType = atoi(optarg); break; - case 'Q': + case 'q': touchSensor0Address = atoi(optarg); break; - case 'R': + case 'r': touchSensor1Address = atoi(optarg); break; case 'l': @@ -361,7 +363,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings RT_TASK rtSensorThread; const char rtSensorThreadName[] = "dbox-sensor"; int oscBankHopSize; @@ -371,7 +373,7 @@ args.argv = argv; parseArguments(args, &settings); - setVerboseLevel(gVerbose); + BeagleRT_setVerboseLevel(gVerbose); if(gVerbose == 1 && useAudioTest) cout << "main() : running in audio test mode" << endl; @@ -415,7 +417,7 @@ if(gVerbose==1) cout << "main() : creating control thread" << endl; - if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, 95, T_JOINABLE | T_FPU)) { + if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BEAGLERT_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) { cout << "Error:unable to create Xenomai control thread" << endl; return -1; }
--- a/projects/d-box/render.cpp Thu May 28 17:48:42 2015 -0400 +++ b/projects/d-box/render.cpp Sat May 30 12:34:32 2015 -0500 @@ -5,7 +5,7 @@ * Author: Victor Zappi */ -#include "../../include/RTAudio.h" +#include "../../include/BeagleRT.h" #include "../../include/PRU.h" #include "StatusLED.h" #include "config.h" @@ -39,7 +39,6 @@ #define ADC_PIN6 6 #define ADC_PIN7 7 - #define N_OCT 4.0 // maximum number of octaves on sensor 1 extern vector<OscillatorBank*> gOscBanks; @@ -49,7 +48,6 @@ extern StatusLED gStatusLED; extern bool gIsLoading; extern bool gAudioIn; -extern int gPeriodSize; float *gOscillatorBuffer1, *gOscillatorBuffer2; float *gOscillatorBufferRead, *gOscillatorBufferWrite; @@ -78,7 +76,7 @@ // sensor 0. extern float gSensor0LatestTouchPos; extern int gSensor0LatestTouchNum; -uint16_t gPitchLatestInput = 0; +float gPitchLatestInput = 0; extern float gSensor1LatestTouchPos[]; //extern float gSensor1LatestTouchSizes[]; @@ -94,9 +92,9 @@ // Loop points from matrix input 4 const int gLoopPointsInputBufferSize = 256; -uint16_t gLoopPointsInputBuffer[gLoopPointsInputBufferSize]; +float gLoopPointsInputBuffer[gLoopPointsInputBufferSize]; int gLoopPointsInputBufferPointer = 0; -int gLoopPointMin = 0, gLoopPointMax = 0; +float gLoopPointMin = 0, gLoopPointMax = 0; // multiplier to activate or mute audio in int audioInStatus = 0; @@ -106,7 +104,7 @@ // pitch vars float octaveSplitter; -u_int16_t semitones[((int)N_OCT*12)+1]; +float semitones[((int)N_OCT*12)+1]; float deltaTouch = 0; float deltaWeightP = 0.5; float deltaWeightI = 0.0005; @@ -143,22 +141,21 @@ float *tableIn, float *tableOut, float *sineTable, float sineMix); -inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, - uint16_t fallingThreshold, bool *rising); +inline float hysteresis_oscillator(float input, float risingThreshold, + float fallingThreshold, bool *rising); + +void render_medium_prio(); +void render_low_prio(); #ifdef DBOX_CAPE_TEST void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, uint16_t *matrixIn, uint16_t *matrixOut); #endif -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) { +bool initialise_render(BeagleRTContext *context, void *userData) { int oscBankHopSize = *(int *)userData; - if(numMatrixChannels != 8) { + if(context->analogChannels != 8) { printf("Error: D-Box needs matrix enabled with 8 channels.\n"); return false; } @@ -166,19 +163,19 @@ // Allocate two buffers for rendering oscillator bank samples // One will be used for writing in the background while the other is used for reading // on the audio thread. 8-byte alignment needed for the NEON code. - if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { + if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * context->audioChannels * sizeof(float))) { printf("Error allocating render buffers\n"); return false; } - if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { + if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * context->audioChannels * sizeof(float))) { printf("Error allocating render buffers\n"); return false; } gOscillatorBufferWrite = gOscillatorBuffer1; gOscillatorBufferRead = gOscillatorBuffer2; - memset(gOscillatorBuffer1, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); - memset(gOscillatorBuffer2, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); + memset(gOscillatorBuffer1, 0, oscBankHopSize * context->audioChannels * sizeof(float)); + memset(gOscillatorBuffer2, 0, oscBankHopSize * context->audioChannels * sizeof(float)); // Initialise the dynamic wavetable used by the oscillator bank // It should match the size of the static one already allocated in the OscillatorBank object @@ -189,18 +186,18 @@ return false; } - gFeedbackOscillator.initialise(8192, 10.0, matrixSampleRate); + gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate); for(int n = 0; n < gDynamicWavetableLength + 1; n++) gDynamicWavetable[n] = 0; // pitch - float midPos = (float)65535/2.0; - octaveSplitter = round((float)65535/(N_OCT)); + float midPos = 0.5; + octaveSplitter = 1.0 / N_OCT; int numOfSemi = 12*N_OCT; int middleSemitone = 12*N_OCT/2; int lastSemitone = middleSemitone+numOfSemi/2; - float inc = (float)65535/(N_OCT*12.0); + float inc = 1.0 / (N_OCT*12.0); int i = -1; for(int semi=middleSemitone; semi<=lastSemitone; semi++) semitones[semi] = ( midPos + (++i)*inc) + 0.5; @@ -212,7 +209,7 @@ audioInStatus = 1; // filter - blockSize = 2*gPeriodSize; + blockSize = context->audioFrames; filterState[0] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); filterState[1] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); filterIn[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); @@ -223,24 +220,23 @@ ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize); // peak outputs - PeakBurst[0].setAttackRate(.00001 * matrixSampleRate); - PeakBurst[1].setAttackRate(.00001 * matrixSampleRate); - PeakBurst[0].setDecayRate(.5 * matrixSampleRate); - PeakBurst[1].setDecayRate(.5 * matrixSampleRate); + PeakBurst[0].setAttackRate(.00001 * context->analogSampleRate); + PeakBurst[1].setAttackRate(.00001 * context->analogSampleRate); + PeakBurst[0].setDecayRate(.5 * context->analogSampleRate); + PeakBurst[1].setDecayRate(.5 * context->analogSampleRate); PeakBurst[0].setSustainLevel(0.0); PeakBurst[1].setSustainLevel(0.0); // Initialise auxiliary tasks - if((gMediumPriorityRender = createAuxiliaryTaskLoop(&render_medium_prio, 90, "dbox-calculation-medium")) == 0) + if((gMediumPriorityRender = BeagleRT_createAuxiliaryTask(&render_medium_prio, BEAGLERT_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0) return false; - if((gLowPriorityRender = createAuxiliaryTaskLoop(&render_low_prio, 85, "dbox-calculation-low")) == 0) + if((gLowPriorityRender = BeagleRT_createAuxiliaryTask(&render_low_prio, BEAGLERT_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0) return false; return true; } -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { #ifdef DBOX_CAPE_TEST render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut); @@ -250,10 +246,10 @@ if(gOscBanks[gCurrentOscBank]->state==bank_playing) { - assert(gNumAudioChannels == 2); + assert(context->audioChannels == 2); #ifdef OLD_OSCBANK - memset(audioOut, 0, numAudioFrames * gNumAudioChannels * sizeof(float)); + memset(audioOut, 0, numAudioFrames * * sizeof(float)); /* Render the oscillator bank. The oscillator bank function is written in NEON assembly * and it strips out all extra checks, so find out in advance whether we can render a whole @@ -290,18 +286,18 @@ gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/); framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter; - audioOutWithOffset += gNumAudioChannels * gOscBanks[gCurrentOscBank]->hopCounter; + audioOutWithOffset += * gOscBanks[gCurrentOscBank]->hopCounter; gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter; gOscBanks[gCurrentOscBank]->nextHop(); } } #else - for(int n = 0; n < numAudioFrames; n++) { - audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n]*audioInStatus; - audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n+1]*audioInStatus; + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n]*audioInStatus; + context->audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n+1]*audioInStatus; - filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 - filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 + filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1 + filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2 /* FIXME why doesn't this work? */ /* @@ -326,19 +322,19 @@ gOscillatorBufferReadPointer = 0; gOscillatorNeedsRender = true; - scheduleAuxiliaryTask(gMediumPriorityRender); + BeagleRT_scheduleAuxiliaryTask(gMediumPriorityRender); } } #endif } else { - for(int n = 0; n < numAudioFrames; n++) { - audioOut[2*n] = audioIn[2*n]*audioInStatus; - audioOut[2*n + 1] = audioIn[2*n+1]*audioInStatus; + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = context->audioIn[2*n]*audioInStatus; + context->audioOut[2*n + 1] = context->audioIn[2*n+1]*audioInStatus; - filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 - filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 + filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1 + filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2 } } @@ -346,7 +342,7 @@ ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize); ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize); - for(int n = 0; n < numMatrixFrames; n++) { + for(unsigned int n = 0; n < context->analogFrames; n++) { /* Matrix Out 0, In 0 @@ -354,12 +350,12 @@ * CV loop * Controls pitch of sound */ - int touchPosInt = gSensor0LatestTouchPos * 65536.0; + float touchPosInt = gSensor0LatestTouchPos; if(touchPosInt < 0) touchPosInt = 0; - if(touchPosInt > 65535) touchPosInt = 65535; - matrixOut[n*8 + DAC_PIN0] = touchPosInt; + if(touchPosInt > 1.0) touchPosInt = 1.0; + context->analogOut[n*8 + DAC_PIN0] = touchPosInt; - gPitchLatestInput = matrixIn[n*8 + ADC_PIN0]; + gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0]; /* Matrix Out 7 @@ -372,17 +368,17 @@ if(gSensor0LatestTouchNum>0) { // current pitch is gPitchLatestInput, already retrieved - semitoneIndex = ( ( (float)gPitchLatestInput / 65535)*12*N_OCT )+0.5; // closest semitone + semitoneIndex = ( gPitchLatestInput * 12 * N_OCT )+0.5; // closest semitone deltaTarget = (semitones[semitoneIndex]-gPitchLatestInput); // delta between pitch and target deltaTouch += deltaTarget*deltaWeightI; // update feedback [previous + current] } else deltaTouch = 0; - int nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out + float nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out if(nextOut < 0) nextOut = 0; // clamp - if(nextOut > 65535) nextOut = 65535; // clamp - matrixOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut + if(nextOut > 1.0) nextOut = 1.0; // clamp + context->analogOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut /* @@ -392,7 +388,8 @@ * Controls speed of playback */ bool wasRising = gSpeedHysteresisOscillatorRising; - matrixOut[n*8 + DAC_PIN1] = hysteresis_oscillator(matrixIn[n*8 + ADC_PIN1], 48000, 16000, &gSpeedHysteresisOscillatorRising); + context->analogOut[n*8 + DAC_PIN1] = hysteresis_oscillator(context->analogIn[n*8 + ADC_PIN1], 48000.0/65536.0, + 16000.0/65536.0, &gSpeedHysteresisOscillatorRising); // Find interval of zero crossing if(wasRising && !gSpeedHysteresisOscillatorRising) { @@ -415,12 +412,12 @@ * Controls wavetable used for oscillator bank */ - int tableLength = gFeedbackOscillator.process(matrixIn[n*8 + ADC_PIN2], &matrixOut[n*8 + DAC_PIN2]); + int tableLength = gFeedbackOscillator.process(context->analogIn[n*8 + ADC_PIN2], &context->analogOut[n*8 + DAC_PIN2]); if(tableLength != 0) { gFeedbackOscillatorTableLength = tableLength; gFeedbackOscillatorTable = gFeedbackOscillator.wavetable(); gDynamicWavetableNeedsRender = true; - scheduleAuxiliaryTask(gLowPriorityRender); + BeagleRT_scheduleAuxiliaryTask(gLowPriorityRender); } /* @@ -432,10 +429,10 @@ */ volatile int touchCount = gSensor1LatestTouchCount; if(touchCount == 0) - matrixOut[n*8 + DAC_PIN3] = 0; + context->analogOut[n*8 + DAC_PIN3] = 0; else { int touchIndex = (gMatrixSampleCount >> 5) % touchCount; - matrixOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f; + context->analogOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f / 65536.0f; if(touchIndex != gSensor1LastTouchIndex) { // Just changed to a new touch output. Reset the counter. // It will take 2*matrixFrames samples for this output to come back to the @@ -443,33 +440,33 @@ // let's say 24 samples into it. // FIXME this won't work for p > 2 - gSensor1InputDelayCounter = 24 + 2*numMatrixFrames; + gSensor1InputDelayCounter = 24 + 2*context->analogFrames; gSensor1InputIndex = touchIndex; } gSensor1LastTouchIndex = touchIndex; } if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) { - gSensor1MatrixTouchPos[gSensor1InputIndex] = (float)matrixIn[n*8 + ADC_PIN3] / 65536.0f; + gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3]; } /* Matrix Out 4 * * Sensor 1 last pos */ - touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex] * 65536.0; + touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex]; if(touchPosInt < 0) touchPosInt = 0; - if(touchPosInt > 65535) touchPosInt = 65535; - matrixOut[n*8 + DAC_PIN4] = touchPosInt; + if(touchPosInt > 1.0) touchPosInt = 1.0; + context->analogOut[n*8 + DAC_PIN4] = touchPosInt; /* Matrix In 4 * * Loop points selector */ - gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = matrixIn[n*8 + ADC_PIN4]; + gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4]; if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) { // Find min and max values - uint16_t loopMax = 0, loopMin = 65535; + float loopMax = 0, loopMin = 1.0; for(int i = 0; i < gLoopPointsInputBufferSize; i++) { if(gLoopPointsInputBuffer[i] < loopMin) loopMin = gLoopPointsInputBuffer[i]; @@ -503,8 +500,8 @@ PeakBurst[0].process(1); - int convAudio = burstOut*peak[0]*65535; - matrixOut[n*8 + DAC_PIN5] = convAudio; + float convAudio = burstOut*peak[0]; + context->analogOut[n*8 + DAC_PIN5] = convAudio; prevFiltered[0] = filterOut[0][n*2+1]; if(prevFiltered[0]>1) prevFiltered[0] = 1; @@ -513,8 +510,8 @@ * * Dissonance, via changing frequency motion of partials */ - float amount = (float)matrixIn[n*8 + ADC_PIN5] / 65536.0f; - gOscBanks[gCurrentOscBank]->freqMovement = 1-amount; + float amount = (float)context->analogIn[n*8 + ADC_PIN5]; + gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount; @@ -537,8 +534,8 @@ PeakBurst[1].process(1); - convAudio = burstOut*peak[1]*65535; - matrixOut[n*8 + DAC_PIN6] = convAudio; + convAudio = burstOut*peak[1]; + context->analogOut[n*8 + DAC_PIN6] = convAudio; prevFiltered[1] = filterOut[1][n*2+1]; if(prevFiltered[1]>1) prevFiltered[1] = 1; @@ -550,14 +547,14 @@ if(!gIsLoading) { // Use hysteresis to avoid jumping back and forth between sounds if(gOscBanks.size() > 1) { - int input = matrixIn[n*8 + ADC_PIN6]; - const int hystValue = 16000; + float input = context->analogIn[n*8 + ADC_PIN6]; + const float hystValue = 16000.0 / 65536.0; - int upHysteresisValue = ((gCurrentOscBank + 1) * 65536 + hystValue) / gOscBanks.size(); - int downHysteresisValue = (gCurrentOscBank * 65536 - hystValue) / gOscBanks.size(); + float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size(); + float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size(); if(input > upHysteresisValue || input < downHysteresisValue) { - gNextOscBank = input * gOscBanks.size() / 65536; + gNextOscBank = input * gOscBanks.size(); if(gNextOscBank < 0) gNextOscBank = 0; if((unsigned)gNextOscBank >= gOscBanks.size()) @@ -572,8 +569,8 @@ * FSR from primary touch sensor * Value ranges from 0-1799 */ - gLastFSRValue = matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); - //gLastFSRValue = 1799 - matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); + gLastFSRValue = context->analogIn[n*8 + ADC_PIN7] * 1799.0; + //gLastFSRValue = 1799 - context->analogIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); //dbox_printf("%i\n",gLastFSRValue); gMatrixSampleCount++; @@ -590,7 +587,7 @@ gOscillatorNeedsRender = false; /* Render one frame into the write buffer */ - memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels * sizeof(float)); + memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * 2 * sizeof(float)); /* assumes 2 audio channels */ oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite, gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize, @@ -600,7 +597,7 @@ gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable); - gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels; + gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2; /* Update the pitch right before the hop * Total CV range +/- N_OCT octaves @@ -681,7 +678,7 @@ gOscBanks[gCurrentOscBank]->lookupTable, sineMix); } - if(gLoopPointMin >= 60000 && gLoopPointMax >= 60000) { + if(gLoopPointMin >= 60000.0/65536.0 && gLoopPointMax >= 60000.0/65536.0) { // KLUDGE! if(gCurrentOscBank == 0) gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1); @@ -689,8 +686,8 @@ gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1); } else { - float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; - float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; + float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop(); + float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop(); int intLoopPointMin = normLoopPointMin; if(intLoopPointMin < 1) @@ -733,7 +730,7 @@ } // Clean up at the end of render -void cleanup_render() +void cleanup_render(BeagleRTContext *context, void *userData) { free(gOscillatorBuffer1); free(gOscillatorBuffer2); @@ -765,9 +762,9 @@ } // Create a hysteresis oscillator with a matrix input and output -inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, uint16_t fallingThreshold, bool *rising) +inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising) { - uint16_t value; + float value; if(*rising) { if(input > risingThreshold) { @@ -775,12 +772,12 @@ value = 0; } else - value = 65535; + value = 1.0; } else { if(input < fallingThreshold) { *rising = true; - value = 65535; + value = 1.0; } else value = 0;