Development checkin

master
Steve Lascos 7 years ago
parent eb86b4313f
commit 9fd96aa5e3
  1. 94
      src/AudioEffectAnalogDelay.cpp
  2. 5
      src/AudioEffectAnalogDelay.h
  3. 7
      src/BASpiMemory.cpp
  4. 9
      src/BASpiMemory.h
  5. 33
      src/LibBasicFunctions.cpp
  6. 6
      src/LibBasicFunctions.h
  7. 140
      src/LibMemoryManagement.cpp
  8. 22
      src/LibMemoryManagement.h

@ -28,14 +28,19 @@ AudioEffectAnalogDelay::AudioEffectAnalogDelay(size_t numSamples)
}
// requires preallocated memory large enough
AudioEffectAnalogDelay::AudioEffectAnalogDelay(ExtMemSlot &slot)
AudioEffectAnalogDelay::AudioEffectAnalogDelay(ExtMemSlot *slot)
: AudioStream(1, m_inputQueueArray)
{
// m_memory = &slot;
// for (int i=0; i<MAX_DELAY_CHANNELS; i++) {
// m_channelOffsets[i] = 0;
// }
// m_memory->clear();
m_memory = new AudioDelay(slot);
m_externalMemory = true;
for (int i=0; i<MAX_DELAY_CHANNELS; i++) {
m_channelOffsets[i] = 0;
}
}
AudioEffectAnalogDelay::~AudioEffectAnalogDelay()
{
if (m_memory) delete m_memory;
}
void AudioEffectAnalogDelay::update(void)
@ -66,11 +71,19 @@ void AudioEffectAnalogDelay::update(void)
m_callCount++;
Serial.println(String("AudioEffectAnalgDelay::update: ") + m_callCount);
m_memory->getSlot()->printStatus();
audio_block_t *blockToRelease = m_memory->addBlock(inputAudioBlock);
// if (inputAudioBlock) {
// transmit(inputAudioBlock, 0);
// release(inputAudioBlock);
// }
// return;
if (blockToRelease) release(blockToRelease);
//Serial.print("Active channels: "); Serial.print(m_activeChannels, HEX); Serial.println("");
Serial.print("Active channels: "); Serial.print(m_activeChannels, HEX); Serial.println("");
// For each active channel, output the delayed audio
@ -92,6 +105,7 @@ void AudioEffectAnalogDelay::update(void)
blockToOutput = allocate(); // allocate if spanning 2 queues
}
} else {
// external memory
blockToOutput = allocate(); // allocate always for external memory
}
@ -112,26 +126,21 @@ bool AudioEffectAnalogDelay::delay(unsigned channel, float milliseconds)
size_t delaySamples = calcAudioSamples(milliseconds);
// if (!m_externalMemory) {
// // Internal memory (AudioStream buffers)
//
// QueuePosition queuePosition = calcQueuePosition(milliseconds);
// Serial.println(String("CONFIG(") + m_memory->getMaxSize() + String("): delay: queue position ") + queuePosition.index + String(":") + queuePosition.offset);
// // we have to take the queue position and add 1 to get the number of queues. But we need to add one more since this
// // is the start of the audio buffer, and the AUDIO_BLOCK_SAMPLES will then flow into the next one, so add 2 overall.
// size_t numQueues = queuePosition.index+2;
// if (numQueues > m_numQueues)
// m_numQueues = numQueues;
// } else {
//// // External memory
//// if (delaySamples > m_memory->getSize()) {
//// // error, the external memory is not large enough
//// return false;
//// }
// }
if (!m_externalMemory) {
// internal memory
QueuePosition queuePosition = calcQueuePosition(milliseconds);
Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
} else {
// external memory
Serial.println(String("CONFIG: delay:") + delaySamples);
ExtMemSlot *slot = m_memory->getSlot();
if (!slot->isEnabled()) {
slot->enable();
} else {
Serial.println("ERROR: slot ptr is not valid");
}
}
QueuePosition queuePosition = calcQueuePosition(milliseconds);
Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
m_channelOffsets[channel] = delaySamples;
m_activeChannels |= 1<<channel;
return true;
@ -142,28 +151,17 @@ bool AudioEffectAnalogDelay::delay(unsigned channel, size_t delaySamples)
if (channel > MAX_DELAY_CHANNELS-1) // channel id too high
return false;
// if (!m_externalMemory) {
// // Internal memory (AudioStream buffers)
// MemAudioBlock *memory = reinterpret_cast<MemAudioBlock*>(m_memory);
//
// //QueuePosition queuePosition = calcQueuePosition(milliseconds);
// QueuePosition queuePosition = calcQueuePosition(delaySamples);
// Serial.println(String("CONFIG(") + memory->getMaxSize() + String("): delay: queue position ") + queuePosition.index + String(":") + queuePosition.offset);
// // we have to take the queue position and add 1 to get the number of queues. But we need to add one more since this
// // is the start of the audio buffer, and the AUDIO_BLOCK_SAMPLES will then flow into the next one, so add 2 overall.
// size_t numQueues = queuePosition.index+2;
// if (numQueues > m_numQueues)
// m_numQueues = numQueues;
// } else {
//// // External memory
//// if (delaySamples > m_memory->getSize()) {
//// // error, the external memory is not large enough
//// return false;
//// }
// }
QueuePosition queuePosition = calcQueuePosition(delaySamples);
Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
if (!m_externalMemory) {
// internal memory
QueuePosition queuePosition = calcQueuePosition(delaySamples);
Serial.println(String("CONFIG: delay:") + delaySamples + String(" queue position ") + queuePosition.index + String(":") + queuePosition.offset);
} else {
// external memory
ExtMemSlot *slot = m_memory->getSlot();
if (!slot->isEnabled()) {
slot->enable();
}
}
m_channelOffsets[channel] = delaySamples;
m_activeChannels |= 1<<channel;
return true;

@ -24,9 +24,8 @@ public:
AudioEffectAnalogDelay() = delete;
AudioEffectAnalogDelay(float maxDelay);
AudioEffectAnalogDelay(size_t numSamples);
AudioEffectAnalogDelay(ExtMemSlot &slot); // requires sufficiently sized pre-allocated memory
virtual ~AudioEffectAnalogDelay() {}
AudioEffectAnalogDelay(ExtMemSlot *slot); // requires sufficiently sized pre-allocated memory
virtual ~AudioEffectAnalogDelay();
virtual void update(void);
bool delay(unsigned channel, float milliseconds);

@ -60,7 +60,6 @@ BASpiMemory::BASpiMemory(SpiDeviceId memDeviceId, uint32_t speedHz)
// Intitialize the correct Arduino SPI interface
void BASpiMemory::begin()
{
switch (m_memDeviceId) {
case SpiDeviceId::SPI_DEVICE0 :
m_csPin = SPI_CS_MEM0;
@ -89,6 +88,7 @@ void BASpiMemory::begin()
pinMode(m_csPin, OUTPUT);
digitalWrite(m_csPin, HIGH);
m_started = true;
}
@ -185,6 +185,7 @@ void BASpiMemory::zero16(size_t address, size_t numWords)
m_spi->endTransaction();
digitalWrite(m_csPin, HIGH);
Serial.println("DONE!");
}
// single address read
@ -239,10 +240,10 @@ uint16_t BASpiMemory::read16(size_t address)
return data;
}
void BASpiMemory::read16(size_t address, uint16_t *data, size_t numWords)
void BASpiMemory::read16(size_t address, uint16_t *dest, size_t numWords)
{
uint16_t *dataPtr = data;
uint16_t *dataPtr = dest;
m_spi->beginTransaction(m_settings);
digitalWrite(m_csPin, LOW);
m_spi->transfer16((SPI_READ_CMD << 8) | (address >> 16) );

@ -71,14 +71,21 @@ public:
/// @param address the address in the SPI RAM to read from
/// @return the data that was read
uint16_t read16(size_t address);
void read16(size_t address, uint16_t *data, size_t numWords);
/// read a block 16-bit data word from the specified address
/// @param address the address in the SPI RAM to read from
/// @param dest the pointer to the destination
/// @param numWords the number of 16-bit words to transfer
void read16(size_t address, uint16_t *dest, size_t numWords);
bool isStarted() const { return m_started; }
private:
SPIClass *m_spi = nullptr;
SpiDeviceId m_memDeviceId; // the MEM device being control with this instance
uint8_t m_csPin; // the IO pin number for the CS on the controlled SPI device
SPISettings m_settings; // the Wire settings for this SPI port
bool m_started = false;
};

@ -49,7 +49,7 @@ AudioDelay::AudioDelay(float maxDelayTimeMs)
}
AudioDelay::AudioDelay(ExtMemSlot &slot)
AudioDelay::AudioDelay(ExtMemSlot *slot)
: m_slot(slot)
{
m_type = MemType::MEM_EXTERNAL;
@ -77,8 +77,17 @@ audio_block_t* AudioDelay::addBlock(audio_block_t *block)
return blockToRelease;
} else {
// EXTERNAL memory
m_slot.writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
return nullptr;
//m_slot->writeAdvance16(block->data, AUDIO_BLOCK_SAMPLES);
// Audio is stored in reverse in block so we need to write it backwards to external memory
// to maintain temporal coherency.
int16_t *srcPtr = block->data + AUDIO_BLOCK_SAMPLES - 1;
for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
m_slot->writeAdvance16(*srcPtr);
srcPtr--;
}
return block;
}
@ -131,8 +140,22 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offset, size_t numSample
} else {
// EXTERNAL Memory
if (numSamples < m_slot.size() ) {
m_slot.read16FromCurrent(dest->data, offset, numSamples);
if (numSamples <= m_slot->size() ) {
int currentPosition = (int)m_slot->getWritePosition() - (int)AUDIO_BLOCK_SAMPLES;
if ((int)offset <= currentPosition) {
m_slot->setReadPosition(currentPosition - offset);
} else {
// It's going to wrap around to the end of the slot
int readPosition = (int)m_slot->size() + currentPosition - offset;
m_slot->setReadPosition((size_t)readPosition);
}
// write the data to the destination block in reverse
int16_t *destPtr = dest->data + AUDIO_BLOCK_SAMPLES-1;
for (int i=0; i<AUDIO_BLOCK_SAMPLES; i++) {
*destPtr = m_slot->readAdvance16();
}
return true;
} else {
// numSampmles is > than total slot size

@ -43,7 +43,7 @@ public:
AudioDelay() = delete;
AudioDelay(size_t maxSamples);
AudioDelay(float maxDelayTimeMs);
AudioDelay(ExtMemSlot &slot);
AudioDelay(ExtMemSlot *slot);
~AudioDelay();
// Internal memory member functions
@ -52,12 +52,12 @@ public:
bool getSamples(audio_block_t *dest, size_t offset, size_t numSamples = AUDIO_BLOCK_SAMPLES);
// External memory member functions
//bool writeBlock(audio_blocK_t *blockIn);
ExtMemSlot *getSlot() const { return m_slot; }
private:
MemType m_type;
RingBuffer<audio_block_t *> *m_ringBuffer = nullptr;
ExtMemSlot &m_slot;
ExtMemSlot *m_slot = nullptr;
};
template <class T>

@ -2,13 +2,12 @@
#include <cstring>
#include <new>
#include "Audio.h"
#include "LibMemoryManagement.h"
namespace BAGuitar {
bool ExternalSramManager::m_configured = false;
MemConfig ExternalSramManager::m_memConfig[BAGuitar::NUM_MEM_SLOTS];
/////////////////////////////////////////////////////////////////////////////
// MEM SLOT
@ -60,34 +59,59 @@ bool ExtMemSlot::read16(int16_t *dest, size_t srcOffset, size_t numData)
}
}
size_t ExtMemSlot::read16FromCurrent(int16_t *dest, size_t currentOffset, size_t numData)
uint16_t ExtMemSlot::readAdvance16()
{
size_t readStart;
if (m_currentPosition + currentOffset <= m_end) {
readStart = m_currentPosition + currentOffset;
uint16_t val = m_spi->read16(m_currentRdPosition);
if (m_currentRdPosition < m_end) {
m_currentRdPosition++;
} else {
// this offset will wrap the memory slot
size_t numBytesToEnd = m_end - m_currentPosition + 1;
readStart = m_start + (currentOffset - numBytesToEnd);
m_currentRdPosition = m_start;
}
m_spi->read16(dest, readStart, numData);
return val;
}
//void ExtMemSlot::read16FromPast(int16_t *dest, size_t currentOffset, size_t numData)
//{
// size_t readStart;
// if (m_currentPosition - currentOffset >= m_start) {
// readStart = m_currentPosition - currentOffset;
// } else {
// // this offset will wrap the memory slot
// size_t numBytesToStart = m_currentPosition;
// readStart = m_end - (currentOffset - numBytesToStart);
// }
// m_spi->read16(readStart, reinterpret_cast<uint16_t*>(dest), numData);
//}
bool ExtMemSlot::writeAdvance16(int16_t *dataPtr, size_t dataSize)
{
if (!m_valid) { return false; }
if (m_currentPosition + dataSize-1 <= m_end) {
if (m_currentWrPosition + dataSize-1 <= m_end) {
// entire block fits in memory slot without wrapping
m_spi->write16(m_currentPosition, reinterpret_cast<uint16_t*>(dataPtr), dataSize); // cast audio data to uint.
m_currentPosition += dataSize;
m_spi->write16(m_currentWrPosition, reinterpret_cast<uint16_t*>(dataPtr), dataSize); // cast audio data to uint.
m_currentWrPosition += dataSize;
} else {
// this write will wrap the memory slot
size_t numBytes = m_end - m_currentPosition + 1;
m_spi->write16(m_currentPosition, reinterpret_cast<uint16_t*>(dataPtr), numBytes);
size_t numBytes = m_end - m_currentWrPosition + 1;
m_spi->write16(m_currentWrPosition, reinterpret_cast<uint16_t*>(dataPtr), numBytes);
size_t remainingBytes = dataSize - numBytes; // calculate the remaining bytes
m_spi->write16(m_start, reinterpret_cast<uint16_t*>(dataPtr + numBytes), remainingBytes); // write remaining bytes are start
m_currentPosition = m_start + remainingBytes;
m_currentWrPosition = m_start + remainingBytes;
}
return true;
}
bool ExtMemSlot::writeAdvance16(int16_t data)
{
if (!m_valid) { return false; }
m_spi->write16(m_currentWrPosition, static_cast<uint16_t>(data));
if (m_currentWrPosition < m_end) {
m_currentWrPosition++;
} else {
m_currentWrPosition = m_start;
}
return true;
}
@ -95,26 +119,55 @@ bool ExtMemSlot::writeAdvance16(int16_t *dataPtr, size_t dataSize)
bool ExtMemSlot::zeroAdvance16(size_t dataSize)
{
if (!m_valid) { return false; }
if (m_currentPosition + dataSize-1 <= m_end) {
if (m_currentWrPosition + dataSize-1 <= m_end) {
// entire block fits in memory slot without wrapping
m_spi->zero16(m_currentPosition, dataSize); // cast audio data to uint.
m_currentPosition += dataSize;
m_spi->zero16(m_currentWrPosition, dataSize); // cast audio data to uint.
m_currentWrPosition += dataSize;
} else {
// this write will wrap the memory slot
size_t numBytes = m_end - m_currentPosition + 1;
m_spi->zero16(m_currentPosition, numBytes);
size_t numBytes = m_end - m_currentWrPosition + 1;
m_spi->zero16(m_currentWrPosition, numBytes);
size_t remainingBytes = dataSize - numBytes; // calculate the remaining bytes
m_spi->zero16(m_start, remainingBytes); // write remaining bytes are start
m_currentPosition = m_start + remainingBytes;
m_currentWrPosition = m_start + remainingBytes;
}
return true;
}
bool ExtMemSlot::enable() const
{
if (m_spi) {
Serial.println("ExtMemSlot::enable()");
m_spi->begin();
return true;
}
else {
Serial.println("ExtMemSlot m_spi is nullptr");
return false;
}
}
bool ExtMemSlot::isEnabled() const
{
if (m_spi) { return m_spi->isStarted(); }
else return false;
}
void ExtMemSlot::printStatus(void) const
{
Serial.println(String("valid:") + m_valid + String(" m_start:") + m_start + \
String(" m_end:") + m_end + String(" m_currentWrPosition: ") + m_currentWrPosition + \
String(" m_size:") + m_size);
}
/////////////////////////////////////////////////////////////////////////////
// EXTERNAL SRAM MANAGER
/////////////////////////////////////////////////////////////////////////////
bool ExternalSramManager::m_configured = false;
MemConfig ExternalSramManager::m_memConfig[BAGuitar::NUM_MEM_SLOTS];
ExternalSramManager::ExternalSramManager(unsigned numMemories)
{
// Initialize the static memory configuration structs
@ -123,7 +176,13 @@ ExternalSramManager::ExternalSramManager(unsigned numMemories)
m_memConfig[i].size = MEM_MAX_ADDR[i];
m_memConfig[i].totalAvailable = MEM_MAX_ADDR[i];
m_memConfig[i].nextAvailable = 0;
m_memConfig[i].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(i));
m_memConfig[i].m_spi = nullptr;
// if (i < numMemories) {
// m_memConfig[i].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(i));
// } else {
// m_memConfig[i].m_spi = nullptr;
// }
}
m_configured = true;
}
@ -141,30 +200,45 @@ size_t ExternalSramManager::availableMemory(BAGuitar::MemSelect mem)
return m_memConfig[mem].totalAvailable;
}
bool ExternalSramManager::requestMemory(ExtMemSlot &slot, float delayMilliseconds, BAGuitar::MemSelect mem)
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem)
{
// convert the time to numer of samples
size_t delayLengthInt = (size_t)((delayMilliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0f))+0.5f);
return requestMemory(slot, delayLengthInt, mem);
}
bool ExternalSramManager::requestMemory(ExtMemSlot &slot, size_t sizeBytes, BAGuitar::MemSelect mem)
bool ExternalSramManager::requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem)
{
if (m_memConfig[mem].totalAvailable >= sizeBytes) {
Serial.println(String("Configuring a slot for mem ") + mem);
// there is enough available memory for this request
slot.m_start = m_memConfig[mem].nextAvailable;
slot.m_end = slot.m_start + sizeBytes -1;
slot.m_currentPosition = slot.m_start; // init to start of slot
slot.m_size = sizeBytes;
slot.m_spi = m_memConfig[mem].m_spi;
slot->m_start = m_memConfig[mem].nextAvailable;
slot->m_end = slot->m_start + sizeBytes -1;
slot->m_currentWrPosition = slot->m_start; // init to start of slot
slot->m_currentRdPosition = slot->m_start; // init to start of slot
slot->m_size = sizeBytes;
if (!m_memConfig[mem].m_spi) {
m_memConfig[mem].m_spi = new BAGuitar::BASpiMemory(static_cast<BAGuitar::SpiDeviceId>(mem));
if (!m_memConfig[mem].m_spi) {
Serial.println("requestMemory: new failed! m_spi is a nullptr");
} else {
m_memConfig[mem].m_spi->begin();
}
}
slot->m_spi = m_memConfig[mem].m_spi;
// Update the mem config
m_memConfig[mem].nextAvailable = slot.m_end+1;
m_memConfig[mem].nextAvailable = slot->m_end+1;
m_memConfig[mem].totalAvailable -= sizeBytes;
slot.m_valid = true;
slot->m_valid = true;
if (!slot->isEnabled()) { slot->enable(); }
slot->clear();
return true;
} else {
// there is not enough memory available for the request
return false;
}
}

@ -32,21 +32,35 @@ class ExtMemSlot {
public:
bool clear();
bool setWritePosition(size_t offset) { m_currentWrPosition = m_start + offset; return true;} // TODO add range check
size_t getWritePosition() const { return m_currentWrPosition-m_start; }
bool setReadPosition(size_t offset) { m_currentRdPosition = m_start + offset; return true;} // TODO add range check
size_t getReadPosition() const { return m_currentRdPosition-m_start; }
bool write16(size_t offset, int16_t *dataPtr, size_t numData);
bool zero16(size_t offset, size_t numData);
bool read16(int16_t *dest, size_t srcOffset, size_t numData);
uint16_t readAdvance16();
bool writeAdvance16(int16_t *dataPtr, size_t numData);
bool writeAdvance16(int16_t data); // write just one data
bool zeroAdvance16(size_t numData);
size_t read16FromCurrent(int16_t *dest, size_t Offset, size_t numData);
//void read16FromPast(int16_t *dest, size_t Offset, size_t numData);
size_t size() const { return m_size; }
bool enable() const;
bool isEnabled() const;
void printStatus(void) const;
private:
friend ExternalSramManager;
bool m_valid = false;
size_t m_start = 0;
size_t m_end = 0;
size_t m_currentPosition = 0;
size_t m_currentWrPosition = 0;
size_t m_currentRdPosition = 0;
size_t m_size = 0;
SpiDeviceId m_spiId;
BASpiMemory *m_spi = nullptr;
};
@ -58,8 +72,8 @@ public:
virtual ~ExternalSramManager();
size_t availableMemory(BAGuitar::MemSelect mem);
bool requestMemory(ExtMemSlot &slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
bool requestMemory(ExtMemSlot &slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
bool requestMemory(ExtMemSlot *slot, float delayMilliseconds, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
bool requestMemory(ExtMemSlot *slot, size_t sizeBytes, BAGuitar::MemSelect mem = BAGuitar::MemSelect::MEM0);
private:
static bool m_configured;

Loading…
Cancel
Save