You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MicroDexed/third-party/TeensyVariablePlayback/src/ResamplingSdReader.h

156 lines
4.0 KiB

//
// Created by Nicholas Newdigate on 10/02/2019.
//
#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H
#define TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H
#include "SD.h"
#include <cstdint>
#include "spi_interrupt.h"
#include "loop_type.h"
#include "interpolation.h"
#include "IndexableFile.h"
#define RESAMPLE_BUFFER_SAMPLE_SIZE 128
#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592
class ResamplingSdReader {
public:
ResamplingSdReader() {
}
void begin(void);
bool playRaw(const char *filename, uint16_t numChannels);
bool playWav(const char *filename);
bool play();
void stop(void);
bool isPlaying(void) { return _playing; }
unsigned int read(void **buf, uint16_t nbyte);
bool readNextValue(int16_t *value, uint16_t channelNumber);
void setPlaybackRate(double f) {
_playbackRate = f;
if (f < 0.0 && _bufferPosition == 0) {
//_file.seek(_file_size);
_bufferPosition = _file_size / 2 - _numChannels;
}
}
double playbackRate() {
return _playbackRate;
}
void setLoopType(loop_type loopType)
{
_loopType = loopType;
}
loop_type getLoopType(){
return _loopType;
}
int available(void);
void reset(void);
void close(void);
void setLoopStart(uint32_t loop_start) {
_loop_start = _header_offset + (loop_start * _numChannels);
}
void setLoopFinish(uint32_t loop_finish) {
// sample number, (NOT byte number)
_loop_finish = _header_offset + (loop_finish * _numChannels);
}
void setInterpolationType(ResampleInterpolationType interpolationType) {
if (interpolationType != _interpolationType) {
_interpolationType = interpolationType;
initializeInterpolationPoints();
}
}
int16_t getNumChannels() {
return _numChannels;
}
void setNumChannels(uint16_t numChannels) {
if (numChannels != _numChannels) {
_numChannels = numChannels;
initializeInterpolationPoints();
}
}
void setHeaderSize(uint32_t headerSizeInBytes) {
_header_offset = headerSizeInBytes / 2;
if (_bufferPosition < _header_offset) {
if (_playbackRate >= 0) {
_bufferPosition = _header_offset;
}
}
}
uint32_t positionMillis(void) {
if (_file_size == 0) return 0;
return (uint32_t) (( (double)_bufferPosition * lengthMillis() ) / (double)(_file_size/2));
}
uint32_t lengthMillis(void) {
return ((uint64_t)_file_size * B2M) >> 32;
}
private:
volatile bool _playing = false;
int32_t _file_size;
int32_t _header_offset = 0; // == (header size in bytes ) / 2
double _playbackRate = 1.0;
double _remainder = 0.0;
loop_type _loopType = looptype_none;
int _bufferPosition = 0;
int32_t _loop_start = 0;
int32_t _loop_finish = 0;
int16_t _numChannels = -1;
uint16_t _numInterpolationPointsChannels = 0;
char *_filename = nullptr;
newdigate::IndexableFile<128, 2> *_sourceBuffer = nullptr;
ResampleInterpolationType _interpolationType = ResampleInterpolationType::resampleinterpolation_none;
unsigned int _numInterpolationPoints = 0;
InterpolationData **_interpolationPoints = nullptr;
static bool isUsingSPI;
void StartUsingSPI(){
if (!isUsingSPI) {
isUsingSPI = true;
#if defined(HAS_KINETIS_SDHC)
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStartUsingSPI();
#else
AudioStartUsingSPI();
#endif
}
}
void StopUsingSPI() {
if (isUsingSPI) {
isUsingSPI = false;
#if defined(HAS_KINETIS_SDHC)
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI();
#else
AudioStopUsingSPI();
#endif
}
}
bool play(const char *filename, bool isWave, uint16_t numChannelsIfRaw = 0);
void initializeInterpolationPoints(void);
void deleteInterpolationPoints(void);
};
#endif //TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H