|
|
@ -6,12 +6,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
namespace BAGuitar { |
|
|
|
namespace BAGuitar { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ExternalSramManager::m_configured = false; |
|
|
|
bool ExternalSramManager::m_configured = false; |
|
|
|
MemConfig ExternalSramManager::m_memConfig[BAGuitar::NUM_MEM_SLOTS]; |
|
|
|
MemConfig ExternalSramManager::m_memConfig[BAGuitar::NUM_MEM_SLOTS]; |
|
|
|
|
|
|
|
|
|
|
|
inline size_t calcAudioSamples(float milliseconds) |
|
|
|
size_t calcAudioSamples(float milliseconds) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return (size_t)((milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f); |
|
|
|
return (size_t)((milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f); |
|
|
|
} |
|
|
|
} |
|
|
@ -42,7 +40,7 @@ size_t calcOffset(QueuePosition position) |
|
|
|
// MEM VIRTUAL
|
|
|
|
// MEM VIRTUAL
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
MemAudioBlock::MemAudioBlock(size_t numSamples) |
|
|
|
MemAudioBlock::MemAudioBlock(size_t numSamples) |
|
|
|
: m_queues((numSamples + AUDIO_BLOCK_SAMPLES - 1)/AUDIO_BLOCK_SAMPLES) |
|
|
|
: m_queues(((numSamples + AUDIO_BLOCK_SAMPLES - 1)/AUDIO_BLOCK_SAMPLES) +1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// // round up to an integer multiple of AUDIO_BLOCK_SAMPLES
|
|
|
|
// // round up to an integer multiple of AUDIO_BLOCK_SAMPLES
|
|
|
|
// int numQueues = (numSamples + AUDIO_BLOCK_SAMPLES - 1)/AUDIO_BLOCK_SAMPLES;
|
|
|
|
// int numQueues = (numSamples + AUDIO_BLOCK_SAMPLES - 1)/AUDIO_BLOCK_SAMPLES;
|
|
|
@ -63,14 +61,28 @@ MemAudioBlock::~MemAudioBlock() |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// the index is referenced from the head
|
|
|
|
|
|
|
|
audio_block_t *MemAudioBlock::getQueueBack(size_t offset) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for (int i=0; i<m_queues.getMaxSize(); i++) {
|
|
|
|
|
|
|
|
// Serial.println(i + String(":") + (uint32_t)m_queues[i]->data);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Serial.println(String("Returning ") + (uint32_t)m_queues[m_queues.getBackIndex(offset)]);
|
|
|
|
|
|
|
|
return m_queues[m_queues.getBackIndex(offset)]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool MemAudioBlock::push(audio_block_t *block) |
|
|
|
bool MemAudioBlock::push(audio_block_t *block) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
//Serial.println("MemAudioBlock::push()");
|
|
|
|
m_queues.push_back(block); |
|
|
|
m_queues.push_back(block); |
|
|
|
|
|
|
|
//Serial.println("MemAudioBlock::push() done");
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
audio_block_t* MemAudioBlock::pop() |
|
|
|
audio_block_t* MemAudioBlock::pop() |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
//Serial.println("MemAudioBlock::pop()");
|
|
|
|
audio_block_t* block = m_queues.front(); |
|
|
|
audio_block_t* block = m_queues.front(); |
|
|
|
m_queues.pop_front(); |
|
|
|
m_queues.pop_front(); |
|
|
|
return block; |
|
|
|
return block; |
|
|
@ -86,7 +98,7 @@ bool MemAudioBlock::clear() |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool MemAudioBlock::write16(size_t offset, int16_t *dataPtr, size_t numData) |
|
|
|
bool MemAudioBlock::write16(size_t offset, int16_t *srcDataPtr, size_t numData) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Calculate the queue position
|
|
|
|
// Calculate the queue position
|
|
|
|
auto position = calcQueuePosition(offset); |
|
|
|
auto position = calcQueuePosition(offset); |
|
|
@ -98,33 +110,38 @@ bool MemAudioBlock::write16(size_t offset, int16_t *dataPtr, size_t numData) |
|
|
|
// loop over a series of memcpys until all data is transferred.
|
|
|
|
// loop over a series of memcpys until all data is transferred.
|
|
|
|
size_t samplesRemaining = numData; |
|
|
|
size_t samplesRemaining = numData; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int16_t *srcStart = srcDataPtr; // this will increment during each loop iteration
|
|
|
|
|
|
|
|
|
|
|
|
while (samplesRemaining > 0) { |
|
|
|
while (samplesRemaining > 0) { |
|
|
|
size_t numSamplesToWrite; |
|
|
|
size_t numSamplesToWrite; |
|
|
|
|
|
|
|
|
|
|
|
void *start = static_cast<void*>(m_queues[index]->data + writeOffset); |
|
|
|
void *destStart = static_cast<void*>(m_queues[index]->data + writeOffset); |
|
|
|
|
|
|
|
|
|
|
|
// determine if the transfer will complete or will hit the end of a block first
|
|
|
|
// determine if the transfer will complete or will hit the end of a block first
|
|
|
|
if ( (writeOffset + samplesRemaining) > AUDIO_BLOCK_SAMPLES ) { |
|
|
|
if ( (writeOffset + samplesRemaining) > AUDIO_BLOCK_SAMPLES ) { |
|
|
|
// goes past end of the queue
|
|
|
|
// goes past end of the queue
|
|
|
|
numSamplesToWrite = (AUDIO_BLOCK_SAMPLES - writeOffset); |
|
|
|
numSamplesToWrite = (AUDIO_BLOCK_SAMPLES - writeOffset); |
|
|
|
writeOffset = 0; |
|
|
|
//writeOffset = 0;
|
|
|
|
index++; |
|
|
|
//index++;
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// transfer ends in this audio block
|
|
|
|
// transfer ends in this audio block
|
|
|
|
numSamplesToWrite = samplesRemaining; |
|
|
|
numSamplesToWrite = samplesRemaining; |
|
|
|
writeOffset += numSamplesToWrite; |
|
|
|
//writeOffset += numSamplesToWrite;
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// perform the transfer
|
|
|
|
// perform the transfer
|
|
|
|
if (!m_queues[index]) { |
|
|
|
if (!m_queues[index]) { |
|
|
|
// no allocated audio block, skip the copy
|
|
|
|
// no allocated audio block, skip the copy
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (dataPtr) { |
|
|
|
if (srcDataPtr) { |
|
|
|
memcpy(start, dataPtr, numSamplesToWrite * sizeof(int16_t)); |
|
|
|
memcpy(destStart, static_cast<const void*>(srcStart), numSamplesToWrite * sizeof(int16_t)); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
memset(start, 0, numSamplesToWrite * sizeof(int16_t)); |
|
|
|
memset(destStart, 0, numSamplesToWrite * sizeof(int16_t)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
writeOffset = 0; |
|
|
|
|
|
|
|
index++; |
|
|
|
|
|
|
|
srcStart += numSamplesToWrite; |
|
|
|
samplesRemaining -= numSamplesToWrite; |
|
|
|
samplesRemaining -= numSamplesToWrite; |
|
|
|
} |
|
|
|
} |
|
|
|
m_currentPosition.offset = writeOffset; |
|
|
|
m_currentPosition.offset = writeOffset; |
|
|
@ -140,44 +157,43 @@ inline bool MemAudioBlock::zero16(size_t offset, size_t numData) |
|
|
|
bool MemAudioBlock::read16(int16_t *dest, size_t destOffset, size_t srcOffset, size_t numSamples) |
|
|
|
bool MemAudioBlock::read16(int16_t *dest, size_t destOffset, size_t srcOffset, size_t numSamples) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!dest) return false; // destination is not valid
|
|
|
|
if (!dest) return false; // destination is not valid
|
|
|
|
|
|
|
|
(void)destOffset; // not supported with audio_block_t;
|
|
|
|
|
|
|
|
//Serial.println("*************************************************************************");
|
|
|
|
|
|
|
|
//Serial.println(String("read16():") + (uint32_t)dest + String(":") + destOffset + String(":") + srcOffset + String(":") + numSamples);
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate the queue position
|
|
|
|
// Calculate the queue position
|
|
|
|
auto position = calcQueuePosition(srcOffset); |
|
|
|
auto position = calcQueuePosition(srcOffset); |
|
|
|
int readOffset = position.offset; |
|
|
|
|
|
|
|
size_t index = position.index; |
|
|
|
size_t index = position.index; |
|
|
|
|
|
|
|
|
|
|
|
if ( (index+1) > m_queues.size()) return false; // out of range
|
|
|
|
// Break the transfer in two. Note that the audio is stored first sample (in time) last (in memory).
|
|
|
|
|
|
|
|
|
|
|
|
// loop over a series of memcpys until all data is transferred.
|
|
|
|
int16_t *destStart = dest; |
|
|
|
size_t samplesRemaining = numSamples; |
|
|
|
audio_block_t *currentQueue; |
|
|
|
|
|
|
|
int16_t *srcStart; |
|
|
|
|
|
|
|
|
|
|
|
while (samplesRemaining > 0) { |
|
|
|
// Break the transfer into two. Note that the audio
|
|
|
|
size_t numSamplesToRead; |
|
|
|
//Serial.println("Calling getQueue");
|
|
|
|
|
|
|
|
currentQueue = getQueueBack(index+1); // buffer indexes go backwards from the back
|
|
|
|
|
|
|
|
//Serial.println(String("Q. Address: ") + (uint32_t)currentQueue + String(" Data: ") + (uint32_t)currentQueue->data);
|
|
|
|
|
|
|
|
srcStart = (currentQueue->data + AUDIO_BLOCK_SAMPLES - position.offset); |
|
|
|
|
|
|
|
size_t numData = position.offset; |
|
|
|
|
|
|
|
//Serial.println(String("Source Start1: ") + (uint32_t)currentQueue->data + String(" Dest start1: ") + (uint32_t)dest);
|
|
|
|
|
|
|
|
//Serial.println(String("copying to ") + (uint32_t)destStart + String(" from ") + (uint32_t)srcStart + String(" numData= ") + numData);
|
|
|
|
|
|
|
|
memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t)); |
|
|
|
|
|
|
|
|
|
|
|
void *srcStart = static_cast<void*>(m_queues[index]->data + readOffset); |
|
|
|
|
|
|
|
void *destStart = static_cast<void *>(dest + destOffset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// determine if the transfer will complete or will hit the end of a block first
|
|
|
|
currentQueue = getQueueBack(index); // buffer indexes go backwards from the back
|
|
|
|
if ( (readOffset + samplesRemaining) > AUDIO_BLOCK_SAMPLES ) { |
|
|
|
//Serial.println(String("Q. Address: ") + (uint32_t)currentQueue + String(" Data: ") + (uint32_t)currentQueue->data);
|
|
|
|
// goes past end of the queue
|
|
|
|
destStart += numData; |
|
|
|
numSamplesToRead = (AUDIO_BLOCK_SAMPLES - readOffset); |
|
|
|
srcStart = (currentQueue->data); |
|
|
|
readOffset = 0; |
|
|
|
numData = AUDIO_BLOCK_SAMPLES - numData; |
|
|
|
index++; |
|
|
|
//Serial.println(String("Source Start2: ") + (uint32_t)currentQueue->data + String(" Dest start2: ") + (uint32_t)dest);
|
|
|
|
} else { |
|
|
|
//Serial.println(String("copying to ") + (uint32_t)destStart + String(" from ") + (uint32_t)srcStart + String(" numData= ") + numData);
|
|
|
|
// transfer ends in this audio block
|
|
|
|
memcpy(static_cast<void*>(destStart), static_cast<void*>(srcStart), numData * sizeof(int16_t)); |
|
|
|
numSamplesToRead = samplesRemaining; |
|
|
|
|
|
|
|
readOffset += numSamplesToRead; |
|
|
|
//m_queues.print();
|
|
|
|
} |
|
|
|
//Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
|
|
|
|
|
|
|
|
|
|
|
// perform the transfer
|
|
|
|
|
|
|
|
if (!m_queues[index]) { |
|
|
|
|
|
|
|
// no allocated audio block, copy zeros
|
|
|
|
|
|
|
|
memset(destStart, 0, numSamplesToRead * sizeof(int16_t)); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
memcpy(srcStart, destStart, numSamplesToRead * sizeof(int16_t)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
samplesRemaining -= numSamplesToRead; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|