forked from PaulStoffregen/Audio
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
resampling .raw audio
- Loading branch information
Showing
5 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// | ||
// Created by Nicholas Newdigate on 10/02/2019. | ||
// | ||
|
||
#include "play_sd_raw_resampled.h" | ||
#include "spi_interrupt.h" | ||
|
||
void AudioPlaySdRawResampled::begin() | ||
{ | ||
playing = false; | ||
file_offset = 0; | ||
file_size = 0; | ||
} | ||
|
||
bool AudioPlaySdRawResampled::play(const char *filename) | ||
{ | ||
stop(); | ||
playing = sdReader.play(filename); | ||
return playing; | ||
} | ||
|
||
void AudioPlaySdRawResampled::stop() | ||
{ | ||
sdReader.stop(); | ||
} | ||
|
||
void AudioPlaySdRawResampled::update() | ||
{ | ||
unsigned int i, n; | ||
audio_block_t *block; | ||
|
||
// only update if we're playing | ||
if (!playing) return; | ||
|
||
// allocate the audio blocks to transmit | ||
block = allocate(); | ||
if (block == NULL) return; | ||
|
||
if (sdReader.available()) { | ||
// we can read more data from the file... | ||
n = sdReader.read(block->data, AUDIO_BLOCK_SAMPLES*2); | ||
file_offset += n; | ||
for (i=n/2; i < AUDIO_BLOCK_SAMPLES; i++) { | ||
block->data[i] = 0; | ||
} | ||
transmit(block); | ||
} else { | ||
sdReader.close(); | ||
#if defined(HAS_KINETIS_SDHC) | ||
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI(); | ||
#else | ||
AudioStopUsingSPI(); | ||
#endif | ||
playing = false; | ||
} | ||
release(block); | ||
} | ||
|
||
#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 | ||
|
||
uint32_t AudioPlaySdRawResampled::positionMillis() | ||
{ | ||
return ((uint64_t)file_offset * B2M) >> 32; | ||
} | ||
|
||
uint32_t AudioPlaySdRawResampled::lengthMillis() | ||
{ | ||
return ((uint64_t)file_size * B2M) >> 32; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// | ||
// Created by Nicholas Newdigate on 10/02/2019. | ||
// | ||
|
||
#ifndef TEENSYAUDIOLIBRARY_PLAY_SD_RAW_RESAMPLED_H | ||
#define TEENSYAUDIOLIBRARY_PLAY_SD_RAW_RESAMPLED_H | ||
#include "Arduino.h" | ||
#include "AudioStream.h" | ||
#include "SD.h" | ||
#include "stdint.h" | ||
#include "utility/ResamplingSdReader.h" | ||
|
||
class AudioPlaySdRawResampled : public AudioStream | ||
{ | ||
public: | ||
AudioPlaySdRawResampled(void) : | ||
AudioStream(0, NULL), | ||
sdReader() | ||
{ | ||
begin(); | ||
} | ||
|
||
void begin(void); | ||
bool play(const char *filename); | ||
void stop(void); | ||
bool isPlaying(void) { return playing; } | ||
uint32_t positionMillis(void); | ||
uint32_t lengthMillis(void); | ||
virtual void update(void); | ||
|
||
void setReadRate(float f) { | ||
sdReader.setReadRate(f); | ||
} | ||
|
||
private: | ||
|
||
uint32_t file_size; | ||
volatile uint32_t file_offset; | ||
volatile bool playing; | ||
ResamplingSdReader sdReader; | ||
}; | ||
|
||
#endif //TEENSYAUDIOLIBRARY_PLAY_SD_RAW_RESAMPLED_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// | ||
// Created by Nicholas Newdigate on 10/02/2019. | ||
// | ||
|
||
#include "ResamplingSdReader.h" | ||
|
||
int ResamplingSdReader::read(void *buf, uint16_t nbyte) { | ||
|
||
unsigned int count = 0; | ||
int16_t *index = (int16_t*)buf; | ||
for (int i=0; i< nbyte/2; i++) { | ||
//Serial.printf("i=%d \n", i); | ||
if (readNextValue(index)) | ||
count+=2; | ||
else | ||
return count; | ||
|
||
index++; | ||
} | ||
return count; | ||
} | ||
|
||
bool ResamplingSdReader::readNextValue(int16_t *value) { | ||
if ( _bufferLength == 0 || _bufferPosition >= _bufferLength) { | ||
// fill buffer from file | ||
unsigned int numRead = 0; | ||
if (_file.available() > 0) { | ||
//Serial.printf("read %d bytes\n", AUDIO_BLOCK_SAMPLES * 2); | ||
numRead = _file.read(_buffer, AUDIO_BLOCK_SAMPLES * 2); | ||
if (numRead == 0) | ||
return false; | ||
_file_offset = _file.position(); | ||
//Serial.printf("numread %d\n", numRead); | ||
} | ||
else | ||
return false; | ||
|
||
_bufferLength = numRead; | ||
_bufferPosition = 0; | ||
} | ||
|
||
//Serial.printf("buf %d/%d \n", _bufferPosition, _bufferLength); | ||
uint16_t result = _buffer[_bufferPosition/2]; | ||
//Serial.printf("result %4x \n", result); | ||
_remainder += _readRate; | ||
|
||
unsigned int delta = static_cast<unsigned int>(_remainder); | ||
_remainder -= static_cast<float>(delta); | ||
|
||
_bufferPosition += 2 * delta; | ||
*value = result; | ||
return true; | ||
} | ||
|
||
void ResamplingSdReader::begin(void) | ||
{ | ||
_playing = false; | ||
_file_offset = 0; | ||
_file_size = 0; | ||
} | ||
|
||
bool ResamplingSdReader::play(const char *filename) | ||
{ | ||
stop(); | ||
#if defined(HAS_KINETIS_SDHC) | ||
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStartUsingSPI(); | ||
#else | ||
AudioStartUsingSPI(); | ||
#endif | ||
__disable_irq(); | ||
_file = SD.open(filename); | ||
__enable_irq(); | ||
if (!_file) { | ||
//Serial.println("unable to open file"); | ||
#if defined(HAS_KINETIS_SDHC) | ||
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI(); | ||
#else | ||
AudioStopUsingSPI(); | ||
#endif | ||
return false; | ||
} | ||
_file_size = _file.size(); | ||
_file_offset = 0; | ||
//Serial.println("able to open file"); | ||
_playing = true; | ||
return true; | ||
} | ||
|
||
void ResamplingSdReader::stop(void) | ||
{ | ||
__disable_irq(); | ||
if (_playing) { | ||
_playing = false; | ||
__enable_irq(); | ||
_file.close(); | ||
#if defined(HAS_KINETIS_SDHC) | ||
if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI(); | ||
#else | ||
AudioStopUsingSPI(); | ||
#endif | ||
} else { | ||
__enable_irq(); | ||
} | ||
} | ||
|
||
int ResamplingSdReader::available(void) { | ||
return _file.available() / _readRate; | ||
} | ||
|
||
void ResamplingSdReader::close(void) { | ||
if (_playing) | ||
stop(); | ||
_file.close(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// Created by Nicholas Newdigate on 10/02/2019. | ||
// | ||
|
||
#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H | ||
#define TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H | ||
|
||
#include "stdint.h" | ||
#include <SD.h> | ||
#include <AudioStream.h> | ||
|
||
#include "../spi_interrupt.h" | ||
|
||
class ResamplingSdReader { | ||
public: | ||
ResamplingSdReader() { | ||
|
||
} | ||
void begin(void); | ||
bool play(const char *filename); | ||
void stop(void); | ||
bool isPlaying(void) { return _playing; } | ||
|
||
int read(void *buf, uint16_t nbyte); | ||
bool readNextValue(int16_t *value); | ||
|
||
void setReadRate(float f) { | ||
_readRate = f; | ||
} | ||
int available(void); | ||
void close(void); | ||
|
||
private: | ||
volatile bool _playing; | ||
volatile uint32_t _file_offset; | ||
|
||
uint32_t _file_size; | ||
float _readRate = 0.5; | ||
float _remainder = 0; | ||
|
||
unsigned int _bufferPosition = 0; | ||
unsigned int _bufferLength = 0; | ||
int16_t _buffer[AUDIO_BLOCK_SAMPLES]; | ||
|
||
File _file; | ||
}; | ||
|
||
|
||
#endif //PAULSTOFFREGEN_RESAMPLINGSDREADER_H |