forked from W4D/soundcube-firmware
158 lines
3.1 KiB
C++
158 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <SD.h>
|
|
#include "ringbuffer.h"
|
|
|
|
struct WaveFile{
|
|
File file;
|
|
|
|
char cstart[4];
|
|
char cwave[4];
|
|
char cfmt[4];
|
|
|
|
bool load(File _file){
|
|
file = _file;
|
|
|
|
// RIFF Header
|
|
uint8_t start[4];
|
|
uint8_t size[4];
|
|
uint8_t wave[4];
|
|
|
|
file.seek(0, SeekSet);
|
|
file.read(start, 4);
|
|
|
|
memcpy(cstart, start, 4);
|
|
|
|
if(strcmp("RIFF", cstart) != 0) return false;
|
|
|
|
file.seek(4, SeekSet);
|
|
file.read(size, 4);
|
|
length = (size[3] << 24) + (size[2] << 16) + (size[1] << 8) + size[3] - 8;
|
|
|
|
file.seek(8, SeekSet);
|
|
file.read(wave, 4);
|
|
memcpy(cwave, wave, 4);
|
|
if(strcmp("WAVE", cwave) != 0) return false;
|
|
|
|
// FORMAT
|
|
uint8_t fmt[4];
|
|
uint8_t fmtLen[4];
|
|
uint8_t fmtTag[2];
|
|
uint8_t fmtChannels[2];
|
|
uint8_t fmtSamplerate[4];
|
|
uint8_t fmtBytesPerSecond[4];
|
|
uint8_t fmtBlockalign[2];
|
|
uint8_t fmtBitsPerSample[2];
|
|
|
|
file.seek(12, SeekSet);
|
|
file.read(fmt, 4);
|
|
memcpy(cfmt, fmt, 4);
|
|
|
|
if(strcmp("fmt ", cfmt) != 0) return false;
|
|
|
|
file.seek(20, SeekSet);
|
|
file.read(fmtTag, 4);
|
|
format = (fmtTag[1] << 8) + fmtTag[0];
|
|
if(format != 0x0001) return false;
|
|
|
|
file.seek(22, SeekSet);
|
|
file.read(fmtChannels, 2);
|
|
channels = (fmtChannels[1] << 8) + fmtChannels[0];
|
|
|
|
file.seek(24, SeekSet);
|
|
file.read(fmtSamplerate, 4);
|
|
samplerate = (fmtSamplerate[3] << 24) + (fmtSamplerate[2] << 16) + (fmtSamplerate[1] << 8) + fmtSamplerate[0];
|
|
|
|
file.seek(32, SeekSet);
|
|
file.read(fmtBlockalign, 2);
|
|
blockalign = (fmtBlockalign[1] << 8) + fmtBlockalign[0];
|
|
|
|
file.seek(34, SeekSet);
|
|
file.read(fmtBitsPerSample, 2);
|
|
bitspersample = (fmtBitsPerSample[1] << 8) + fmtBitsPerSample[0];
|
|
|
|
return true;
|
|
}
|
|
|
|
void readblock(){
|
|
uint8_t samplebyte[blockalign];
|
|
|
|
file.read(samplebyte, blockalign);
|
|
if(!file.available() && loop) file.seek(44, SeekSet);
|
|
|
|
for(int i = 0; i < blockalign; i+=2){
|
|
int16_t sample = (samplebyte[i+1] << 8) + samplebyte[i];
|
|
buffer.push(sample);
|
|
}
|
|
}
|
|
|
|
int16_t get(){
|
|
return buffer.pop();
|
|
}
|
|
|
|
void stop(){
|
|
file.seek(44, SeekSet);
|
|
}
|
|
|
|
bool loop = false;
|
|
uint16_t format = 0;
|
|
uint32_t length = 0;
|
|
uint16_t channels = 0;
|
|
uint32_t samplerate = 0;
|
|
uint16_t blockalign = 0;
|
|
uint16_t bitspersample = 0;
|
|
|
|
RingBuffer<int16_t> buffer;
|
|
};
|
|
|
|
class WaveStream{
|
|
public:
|
|
WaveStream(){}
|
|
|
|
void begin(){
|
|
wavefile.buffer.setSize(24000);
|
|
wavefile.buffer.begin();
|
|
}
|
|
|
|
bool load(File _wavefile){
|
|
if(!wavefile.load(_wavefile)) return false;
|
|
return true;
|
|
}
|
|
|
|
void toggle(){playing = !playing;}
|
|
|
|
void play(){playing = true;}
|
|
|
|
void stop(){
|
|
playing = false;
|
|
wavefile.stop();
|
|
}
|
|
|
|
void pause(){playing = false;}
|
|
|
|
void stream(){
|
|
if(!wavefile.buffer.isFull() && playing){
|
|
int cnt = 0;
|
|
while (!wavefile.buffer.isFull() && cnt < 6000) {
|
|
wavefile.readblock();
|
|
cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int16_t get(){
|
|
return playing ? wavefile.get() : 0;
|
|
}
|
|
|
|
bool isPlaying(){
|
|
return playing;
|
|
}
|
|
|
|
//private:
|
|
|
|
WaveFile wavefile;
|
|
|
|
bool playing = false;
|
|
|
|
|
|
}; |