Fixed a problem with INTERNAL memory on initial filling of RingBuffer

master
Steve Lascos 7 years ago
parent 61d45bff5f
commit 17bbe8216a
  1. 2
      src/AudioEffectAnalogDelay.cpp
  2. 32
      src/LibBasicFunctions.cpp
  3. 13
      src/LibBasicFunctions.h

@ -179,7 +179,7 @@ void AudioEffectAnalogDelay::processMidi(int channel, int control, int value)
if ((m_midiConfig[MIDI_ENABLE][MIDI_CHANNEL] == channel) && if ((m_midiConfig[MIDI_ENABLE][MIDI_CHANNEL] == channel) &&
(m_midiConfig[MIDI_ENABLE][MIDI_CONTROL] == control)) { (m_midiConfig[MIDI_ENABLE][MIDI_CONTROL] == control)) {
// Enable // Enable
if (val >= 65) { enable(); Serial.println(String("AudioEffectAnalogDelay::enable: ON") + value); } if (value >= 65) { enable(); Serial.println(String("AudioEffectAnalogDelay::enable: ON") + value); }
else { disable(); Serial.println(String("AudioEffectAnalogDelay::enable: OFF") + value); } else { disable(); Serial.println(String("AudioEffectAnalogDelay::enable: OFF") + value); }
return; return;
} }

@ -32,7 +32,7 @@ size_t calcOffset(QueuePosition position)
return (position.index*AUDIO_BLOCK_SAMPLES) + position.offset; return (position.index*AUDIO_BLOCK_SAMPLES) + position.offset;
} }
audio_block_t alphaBlend(audio_block_t *out, audio_block_t *dry, audio_block_t* wet, float mix) void alphaBlend(audio_block_t *out, audio_block_t *dry, audio_block_t* wet, float mix)
{ {
for (int i=0; i< AUDIO_BLOCK_SAMPLES; i++) { for (int i=0; i< AUDIO_BLOCK_SAMPLES; i++) {
out->data[i] = (dry->data[i] * (1 - mix)) + (wet->data[i] * mix); out->data[i] = (dry->data[i] * (1 - mix)) + (wet->data[i] * mix);
@ -89,6 +89,7 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
// add the new buffer // add the new buffer
m_ringBuffer->push_back(block); m_ringBuffer->push_back(block);
return blockToRelease; return blockToRelease;
} else { } else {
// EXTERNAL memory // EXTERNAL memory
if (!m_slot) { Serial.println("addBlock(): m_slot is not valid"); } if (!m_slot) { Serial.println("addBlock(): m_slot is not valid"); }
@ -126,35 +127,46 @@ audio_block_t* AudioDelay::getBlock(size_t index)
bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSamples) bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSamples)
{ {
if (!dest) return false; if (!dest) {
Serial.println("getSamples(): dest is invalid");
return false;
}
if (m_type == (MemType::MEM_INTERNAL)) { if (m_type == (MemType::MEM_INTERNAL)) {
QueuePosition position = calcQueuePosition(offset); QueuePosition position = calcQueuePosition(offset);
size_t index = position.index; size_t index = position.index;
audio_block_t *currentQueue0 = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index));
// The latest buffer is at the back. We need index+1 counting from the back.
audio_block_t *currentQueue1 = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index+1));
// check if either queue is invalid, if so just zero the destination buffer
if ( (!currentQueue0) || (!currentQueue0) ) {
// a valid entry is not in all queue positions while it is filling, use zeros
memset(static_cast<void*>(dest->data), 0, numSamples * sizeof(int16_t));
return true;
}
if (position.offset == 0) { if (position.offset == 0) {
// single transfer // single transfer
audio_block_t *currentQueue = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index)); memcpy(static_cast<void*>(dest->data), static_cast<void*>(currentQueue0->data), numSamples * sizeof(int16_t));
memcpy(static_cast<void*>(dest->data), static_cast<void*>(currentQueue->data), numSamples * sizeof(int16_t));
return true; return true;
} }
// Otherwise we need to break the transfer into two memcpy because it will go across two source queues. // Otherwise we need to break the transfer into two memcpy because it will go across two source queues.
// Audio is stored in reverse order. That means the first sample (in time) goes in the last location in the audio block. // Audio is stored in reverse order. That means the first sample (in time) goes in the last location in the audio block.
int16_t *destStart = dest->data; int16_t *destStart = dest->data;
audio_block_t *currentQueue;
int16_t *srcStart; int16_t *srcStart;
// Break the transfer into two. Copy the 'older' data first then the 'newer' data with respect to current time. // Break the transfer into two. Copy the 'older' data first then the 'newer' data with respect to current time.
currentQueue = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index+1)); // The latest buffer is at the back. We need index+1 counting from the back. //currentQueue = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index+1)); // The latest buffer is at the back. We need index+1 counting from the back.
srcStart = (currentQueue->data + AUDIO_BLOCK_SAMPLES - position.offset); srcStart = (currentQueue1->data + AUDIO_BLOCK_SAMPLES - position.offset);
size_t numData = position.offset; size_t numData = position.offset;
memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t)); memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t));
//currentQueue = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index)); // now grab the queue where the 'first' data sample was
currentQueue = m_ringBuffer->at(m_ringBuffer->get_index_from_back(index)); // now grab the queue where the 'first' data sample was
destStart += numData; // we already wrote numData so advance by this much. destStart += numData; // we already wrote numData so advance by this much.
srcStart = (currentQueue->data); srcStart = (currentQueue0->data);
numData = AUDIO_BLOCK_SAMPLES - numData; numData = AUDIO_BLOCK_SAMPLES - numData;
memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t)); memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t));

@ -71,7 +71,7 @@ size_t calcOffset(QueuePosition position);
void clearAudioBlock(audio_block_t *block); void clearAudioBlock(audio_block_t *block);
audio_block_t alphaBlend(audio_block_t *out, audio_block_t *dry, audio_block_t* wet, float mix); void alphaBlend(audio_block_t *out, audio_block_t *dry, audio_block_t* wet, float mix);
template <class T> template <class T>
@ -164,7 +164,7 @@ public:
/// Construct a RingBuffer of specified max size /// Construct a RingBuffer of specified max size
/// @param maxSize number of entries in ring buffer /// @param maxSize number of entries in ring buffer
RingBuffer(const size_t maxSize) : m_maxSize(maxSize) { RingBuffer(const size_t maxSize) : m_maxSize(maxSize) {
m_buffer = new T[maxSize]; m_buffer = new T[maxSize]();
} }
virtual ~RingBuffer(){ virtual ~RingBuffer(){
if (m_buffer) delete [] m_buffer; if (m_buffer) delete [] m_buffer;
@ -199,7 +199,7 @@ public:
if (m_size == 0) { if (m_size == 0) {
// buffer is empty // buffer is empty
Serial.println("RingBuffer::pop_front: buffer is empty\n"); //Serial.println("RingBuffer::pop_front: buffer is empty\n");
return -1; return -1;
} }
if (m_tail < m_maxSize-1) { if (m_tail < m_maxSize-1) {
@ -208,7 +208,7 @@ public:
m_tail = 0; m_tail = 0;
} }
m_size--; m_size--;
Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size); //Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size);
return 0; return 0;
} }
@ -264,10 +264,11 @@ public:
return m_buffer[index]; return m_buffer[index];
} }
/// DEBUG: Prints the status of the Ringbuffer /// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches
void print() const { void print() const {
for (int idx=0; idx<m_maxSize; idx++) { for (int idx=0; idx<m_maxSize; idx++) {
Serial.println(idx + String(" address: ") + (uint32_t)m_buffer[idx] + String(" data: ") + (uint32_t)m_buffer[idx]->data); Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX);
Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX);
} }
} }
private: private:

Loading…
Cancel
Save