diff --git a/OpenAudio_ArduinoLibrary.h b/OpenAudio_ArduinoLibrary.h index fb4388f..735f23c 100644 --- a/OpenAudio_ArduinoLibrary.h +++ b/OpenAudio_ArduinoLibrary.h @@ -10,6 +10,8 @@ #include #include #include "input_i2s_f32.h" +#include "play_queue_f32.h" +#include "record_queue_f32.h" #include #include "synth_sine_f32.h" #include "output_i2s_f32.h" diff --git a/keywords.txt b/keywords.txt index bae2f52..b70fedc 100644 --- a/keywords.txt +++ b/keywords.txt @@ -34,6 +34,8 @@ AudioMemoryUsageMaxReset_F32 KEYWORD1 AudioMixer4_F32 KEYWORD1 AudioMultiply_F32 KEYWORD1 AudioOutputI2S_F32 KEYWORD1 +AudioPlayQueue_F32 KEYWORD1 +AudioRecordQueue_F32 KEYWORD1 AudioSynthWaveform_F32 KEYWORD1 AudioSynthWaveformSine_F32 KEYWORD1 @@ -41,3 +43,4 @@ frequency KEYWORD2 phase KEYWORD2 amplitude KEYWORD2 + diff --git a/play_queue_f32.cpp b/play_queue_f32.cpp new file mode 100644 index 0000000..8583faf --- /dev/null +++ b/play_queue_f32.cpp @@ -0,0 +1,74 @@ +/* +* AudioRecordQueue_F32 +* +* Created: Chip Audette (OpenAudio), Feb 2017 +* Extended from on Teensy Audio Library +* +* License: MIT License. Use at your own risk. +*/ + +#include "play_queue_f32.h" +#include "utility/dspinst.h" + +bool AudioPlayQueue_F32::available(void) +{ + if (userblock) return true; + userblock = allocate_f32(); + if (userblock) return true; + return false; +} + +float32_t * AudioPlayQueue_F32::getBuffer(void) +{ + if (userblock) return userblock->data; + while (1) { + userblock = allocate_f32(); + if (userblock) return userblock->data; + yield(); + } +} + +void AudioPlayQueue_F32::playBuffer(void) +{ + uint32_t h; + + if (!userblock) return; + h = head + 1; + if (h >= 32) h = 0; + while (tail == h) ; // wait until space in the queue + queue[h] = userblock; + head = h; + userblock = NULL; +} + +void AudioPlayQueue_F32::update(void) +{ + audio_block_f32_t *block; + uint32_t t; + + t = tail; + if (t != head) { + if (++t >= 32) t = 0; + block = queue[t]; + tail = t; + transmit(block); + release(block); + } +} + +//assume user already has an audio_block that was NOT allocated by this +//playBuffer. Here, you hand it your buffer. This object takes ownership +//of it and puts it into the queue +void AudioPlayQueue_F32::playAudioBlock(audio_block_f32_t *audio_block) { + uint32_t h; + + if (!audio_block) return; + h = head + 1; + if (h >= 32) h = 0; + while (tail == h) ; // wait until space in the queue + queue[h] = audio_block; + audio_block->ref_count++; //take ownership of this block + head = h; + //userblock = NULL; + +} diff --git a/play_queue_f32.h b/play_queue_f32.h new file mode 100644 index 0000000..0cf9212 --- /dev/null +++ b/play_queue_f32.h @@ -0,0 +1,39 @@ +/* +* AudioPlayQueue_F32 +* +* Created: Chip Audette (OpenAudio), Feb 2017 +* Extended from on Teensy Audio Library +* +* License: MIT License. Use at your own risk. +*/ + +#ifndef play_queue_f32_h_ +#define play_queue_f32_h_ + +#include "Arduino.h" +#include "AudioStream_F32.h" + +class AudioPlayQueue_F32 : public AudioStream_F32 +{ +//GUI: inputs:0, outputs:1 //this line used for automatic generation of GUI node +public: + AudioPlayQueue_F32(void) : AudioStream_F32(0, NULL), + userblock(NULL), head(0), tail(0) { } + //void play(int16_t data); + //void play(const int16_t *data, uint32_t len); + //void play(float32_t data); + //void play(const float32_t *data, uint32_t len); + void playAudioBlock(audio_block_f32_t *); + bool available(void); + float32_t * getBuffer(void); + void playBuffer(void); + void stop(void); + //bool isPlaying(void) { return playing; } + virtual void update(void); +private: + audio_block_f32_t *queue[32]; + audio_block_f32_t *userblock; + volatile uint8_t head, tail; +}; + +#endif diff --git a/record_queue_f32.cpp b/record_queue_f32.cpp new file mode 100644 index 0000000..bc55cc2 --- /dev/null +++ b/record_queue_f32.cpp @@ -0,0 +1,116 @@ +/* Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "record_queue_f32.h" +#include "utility/dspinst.h" + + +int AudioRecordQueue_F32::available(void) +{ + uint32_t h, t; + + h = head; + t = tail; + if (h >= t) return h - t; + return 53 + h - t; +} + +void AudioRecordQueue_F32::clear(void) +{ + uint32_t t; + + if (userblock) { + release(userblock); + userblock = NULL; + } + t = tail; + while (t != head) { + if (++t >= 53) t = 0; + release(queue[t]); + } + tail = t; +} + +float32_t * AudioRecordQueue_F32::readBuffer(void) +{ +// uint32_t t; +// +// if (userblock) return NULL; +// t = tail; +// if (t == head) return NULL; +// if (++t >= 53) t = 0; +// userblock = queue[t]; +// tail = t; +// return userblock->data; + return getAudioBlock()->data; +} + +audio_block_f32_t * AudioRecordQueue_F32::getAudioBlock(void) +{ + uint32_t t; + + if (userblock) return NULL; + t = tail; + if (t == head) return NULL; + if (++t >= 53) t = 0; + userblock = queue[t]; + tail = t; + return userblock; +} + +void AudioRecordQueue_F32::freeBuffer(void) +{ + if (userblock == NULL) return; + release(userblock); + userblock = NULL; +} + +void AudioRecordQueue_F32::freeAudioBlock(void) { + freeBuffer(); +} + +void AudioRecordQueue_F32::update(void) +{ + audio_block_f32_t *block; + uint32_t h; + + block = receiveReadOnly_f32(); + if (!block) return; + if (!enabled) { + release(block); + return; + } + h = head + 1; + if (h >= 53) h = 0; + if (h == tail) { + release(block); + } else { + queue[h] = block; + head = h; + } +} + + diff --git a/record_queue_f32.h b/record_queue_f32.h new file mode 100644 index 0000000..ad39d04 --- /dev/null +++ b/record_queue_f32.h @@ -0,0 +1,45 @@ +/* +* AudioRecordQueue_F32 +* +* Created: Chip Audette (OpenAudio), Feb 2017 +* Extended from on Teensy Audio Library +* +* License: MIT License. Use at your own risk. +*/ + + +#ifndef record_queue_f32_h_ +#define record_queue_f32_h_ + +#include "Arduino.h" +#include "AudioStream_F32.h" + +class AudioRecordQueue_F32 : public AudioStream_F32 +{ +//GUI: inputs:1, outputs:0 //this line used for automatic generation of GUI node +public: + AudioRecordQueue_F32(void) : AudioStream_F32(1, inputQueueArray), + userblock(NULL), head(0), tail(0), enabled(0) { } + void begin(void) { + clear(); + enabled = 1; + } + int available(void); + void clear(void); + //int16_t * readBuffer(void); + float32_t *readBuffer(void); + audio_block_f32_t *getAudioBlock(void); + void freeBuffer(void); + void freeAudioBlock(void); + void end(void) { + enabled = 0; + } + virtual void update(void); +private: + audio_block_f32_t *inputQueueArray[1]; + audio_block_f32_t * volatile queue[53]; + audio_block_f32_t *userblock; + volatile uint8_t head, tail, enabled; +}; + +#endif