@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
*/
# include <cmath>
# include "Audio.h"
# include "Audio.h"
# include "LibBasicFunctions.h"
# include "LibBasicFunctions.h"
@ -105,6 +106,16 @@ size_t AudioDelay::getMaxDelaySamples()
}
}
bool AudioDelay : : getSamples ( audio_block_t * dest , size_t offsetSamples , size_t numSamples )
bool AudioDelay : : getSamples ( audio_block_t * dest , size_t offsetSamples , size_t numSamples )
{
return m_getSamples ( dest - > data , offsetSamples , numSamples ) ;
}
bool AudioDelay : : getSamples ( int16_t * dest , size_t offsetSamples , size_t numSamples )
{
return m_getSamples ( dest , offsetSamples , numSamples ) ;
}
bool AudioDelay : : m_getSamples ( int16_t * dest , size_t offsetSamples , size_t numSamples )
{
{
if ( ! dest ) {
if ( ! dest ) {
Serial . println ( " getSamples(): dest is invalid " ) ;
Serial . println ( " getSamples(): dest is invalid " ) ;
@ -120,53 +131,56 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offsetSamples, size_t nu
audio_block_t * currentQueue1 = m_ringBuffer - > at ( m_ringBuffer - > get_index_from_back ( index + 1 ) ) ;
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
// check if either queue is invalid, if so just zero the destination buffer
if ( ( ! currentQueue0 ) | | ( ! currentQueue0 ) ) {
if ( ( ! currentQueue0 ) | | ( ! currentQueue1 ) ) {
// a valid entry is not in all queue positions while it is filling, use zeros
// 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 ) ) ;
memset ( static_cast < void * > ( dest ) , 0 , numSamples * sizeof ( int16_t ) ) ;
return true ;
return true ;
}
}
if ( position . offset = = 0 ) {
if ( ( position . offset = = 0 ) & & numSamples < = AUDIO_BLOCK_SAMPLES ) {
// single transfer
// single transfer
memcpy ( static_cast < void * > ( dest - > data ) , static_cast < void * > ( currentQueue0 - > data ) , numSamples * sizeof ( int16_t ) ) ;
memcpy ( static_cast < void * > ( dest ) , static_cast < void * > ( currentQueue0 - > 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 ;
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.
// TODO: should AUDIO_BLOCK_SAMPLES on the next line be numSamples?
srcStart = ( currentQueue1 - > 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
destStart + = numData ; // we already wrote numData so advance by this much.
destStart + = numData ; // we already wrote numData so advance by this much.
srcStart = ( currentQueue0 - > data ) ;
srcStart = ( currentQueue0 - > data ) ;
numData = AUDIO_BLOCK_SAMPLES - numData ;
numData = numSamples - 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 ) ) ;
return true ;
return true ;
} else {
} else {
// EXTERNAL Memory
// EXTERNAL Memory
if ( numSamples * sizeof ( int16_t ) < = m_slot - > size ( ) ) {
if ( numSamples * sizeof ( int16_t ) < = m_slot - > size ( ) ) { // check for overflow
int currentPositionBytes = ( int ) m_slot - > getWritePosition ( ) - ( int ) ( AUDIO_BLOCK_SAMPLES * sizeof ( int16_t ) ) ;
// current position is considered the write position subtracted by the number of samples we're going
// to read since this is the smallest delay we can get without reading past the write position into
// the "future".
int currentPositionBytes = ( int ) m_slot - > getWritePosition ( ) - ( int ) ( numSamples * sizeof ( int16_t ) ) ;
size_t offsetBytes = offsetSamples * sizeof ( int16_t ) ;
size_t offsetBytes = offsetSamples * sizeof ( int16_t ) ;
if ( ( int ) offsetBytes < = currentPositionBytes ) {
if ( ( int ) offsetBytes < = currentPositionBytes ) {
// when we back up to read, we won't wrap over the beginning of the slot
m_slot - > setReadPosition ( currentPositionBytes - offsetBytes ) ;
m_slot - > setReadPosition ( currentPositionBytes - offsetBytes ) ;
} else {
} else {
// It's going to wrap around to the end of the slot
// It's going to wrap around to the from the beginning to the end of the slot.
int readPosition = ( int ) m_slot - > size ( ) + currentPositionBytes - offsetBytes ;
int readPosition = ( int ) m_slot - > size ( ) + currentPositionBytes - offsetBytes ;
m_slot - > setReadPosition ( ( size_t ) readPosition ) ;
m_slot - > setReadPosition ( ( size_t ) readPosition ) ;
}
}
// This causes pop s
// Read the number of sample s
m_slot - > readAdvance16 ( dest - > data , AUDIO_BLOCK_SAMPLES ) ;
m_slot - > readAdvance16 ( dest , numSamples ) ;
return true ;
return true ;
} else {
} else {
@ -179,5 +193,18 @@ bool AudioDelay::getSamples(audio_block_t *dest, size_t offsetSamples, size_t nu
}
}
bool AudioDelay : : interpolateDelay ( int16_t * extendedSourceBuffer , int16_t * destBuffer , float fraction , size_t numSamples )
{
int16_t frac1 = static_cast < int16_t > ( 32767.0f * fraction ) ;
int16_t frac2 = 32767 - frac1 ;
// TODO optimize this later
for ( int i = 0 ; i < numSamples ; i + + ) {
destBuffer [ i ] = ( ( frac1 * extendedSourceBuffer [ i ] ) > > 16 ) + ( ( frac2 * extendedSourceBuffer [ i + 1 ] ) > > 16 ) ;
}
return true ;
}
}
}