Kaynağa Gözat

Fix AudioPlaySdWav end-of-data handling

dds
PaulStoffregen 10 yıl önce
ebeveyn
işleme
a2574cb0fc
2 değiştirilmiş dosya ile 51 ekleme ve 38 silme
  1. +48
    -36
      play_sd_wav.cpp
  2. +3
    -2
      play_sd_wav.h

+ 48
- 36
play_sd_wav.cpp Dosyayı Görüntüle

@@ -61,7 +61,8 @@ bool AudioPlaySdWav::play(const char *filename)
stop();
wavfile = SD.open(filename);
if (!wavfile) return false;
buffer_remaining = 0;
buffer_length = 0;
buffer_offset = 0;
state_play = STATE_STOP;
data_length = 0;
state = STATE_PARSE1;
@@ -103,6 +104,8 @@ bool AudioPlaySdWav::start(void)

void AudioPlaySdWav::update(void)
{
int32_t n;

// only update if we're playing
if (state == STATE_STOP) return;

@@ -127,68 +130,75 @@ void AudioPlaySdWav::update(void)
//Serial.println("update");

// is there buffered data?
if (buffer_remaining > 0) {
n = buffer_length - buffer_offset;
if (n > 0) {
// we have buffered data
if (consume()) return; // it was enough to transmit audio
if (consume(n)) return; // it was enough to transmit audio
}

// we only get to this point when buffer[512] is empty
if (state != STATE_STOP && wavfile.available()) {
// we can read more data from the file...
buffer_remaining = wavfile.read(buffer, 512);
if (consume()) {
// good, it resulted in audio transmit
return;
} else {
// not good, no audio was transmitted
buffer_remaining = 0;
if (block_left) {
release(block_left);
block_left = NULL;
}
if (block_right) {
release(block_right);
block_right = NULL;
}
// if we're still playing, well, there's going to
// be a gap in output, but we can't keep burning
// time trying to read more data. Hopefully things
// will go better next time?
if (state != STATE_STOP) return;
buffer_length = wavfile.read(buffer, 512);
if (buffer_length == 0) goto end;
buffer_offset = 0;
if (!consume(buffer_length)) {
// no audio was transmitted
//Serial.println("consume returned false");
if (state != STATE_STOP) goto cleanup;
}
return;
}
// end of file reached or other reason to stop
end: // end of file reached or other reason to stop
wavfile.close();
state_play = STATE_STOP;
state = STATE_STOP;
cleanup:
if (block_left) {
if (block_offset > 0) {
while (block_offset < AUDIO_BLOCK_SAMPLES) {
block_left->data[block_offset++] = 0;
}
transmit(block_left, 0);
if (state < 8 && (state & 1) == 0) {
transmit(block_left, 1);
}
}
release(block_left);
block_left = NULL;
}
if (block_right) {
if (block_offset > 0) {
while (block_offset < AUDIO_BLOCK_SAMPLES) {
block_right->data[block_offset++] = 0;
}
transmit(block_right, 1);
}
release(block_right);
block_right = NULL;
}
state_play = STATE_STOP;
state = STATE_STOP;
}


// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

// Consume already buffered data. Returns true if audio transmitted.
bool AudioPlaySdWav::consume(void)
bool AudioPlaySdWav::consume(uint32_t size)
{
uint32_t len, size;
uint32_t len;
uint8_t lsb, msb;
const uint8_t *p;

size = buffer_remaining;
p = buffer + 512 - size;
p = buffer + buffer_offset;
start:
if (size == 0) return false;
//Serial.print("AudioPlaySdWav write, size = ");
//Serial.print("AudioPlaySdWav write, ");
//Serial.print("size = ");
//Serial.print(size);
//Serial.print(", data_length = ");
//Serial.print(data_length);
//Serial.print(", space = ");
//Serial.println((AUDIO_BLOCK_SAMPLES - block_offset) * 2);
//Serial.print(", state = ");
//Serial.println(state);
switch (state) {
@@ -245,7 +255,8 @@ start:
size -= len;
data_length = header[1];
if (header[0] == 0x61746164) {
//Serial.println("found data chunk");
//Serial.print("wav: found data chunk, len=");
//Serial.println(data_length);
// TODO: verify offset in file is an even number
// as required by WAV format. abort if odd. Code
// below will depend upon this and fail if not even.
@@ -294,13 +305,12 @@ start:
if (block_offset >= AUDIO_BLOCK_SAMPLES) {
transmit(block_left, 0);
transmit(block_left, 1);
//Serial1.print('%');
//delayMicroseconds(90);
release(block_left);
block_left = NULL;
data_length += size;
buffer_remaining = size;
buffer_offset = p - buffer;
if (block_right) release(block_right);
if (data_length == 0) state = STATE_STOP;
return true;
}
if (size == 0) {
@@ -308,6 +318,7 @@ start:
return false;
}
}
//Serial.println("end of file reached");
// end of file reached
if (block_offset > 0) {
// TODO: fill remainder of last block with zero and transmit
@@ -347,7 +358,8 @@ start:
release(block_right);
block_right = NULL;
data_length += size;
buffer_remaining = size;
buffer_offset = p - buffer;
if (data_length == 0) state = STATE_STOP;
return true;
}
if (size == 0) {

+ 3
- 2
play_sd_wav.h Dosyayı Görüntüle

@@ -42,7 +42,7 @@ public:
virtual void update(void);
private:
File wavfile;
bool consume(void);
bool consume(uint32_t size);
bool parse_format(void);
uint32_t header[5];
uint32_t data_length; // number of bytes remaining in data section
@@ -50,7 +50,8 @@ private:
audio_block_t *block_right;
uint16_t block_offset;
uint8_t buffer[512];
uint16_t buffer_remaining;
uint16_t buffer_offset;
uint16_t buffer_length;
uint8_t state;
uint8_t state_play;
uint8_t leftover_bytes;

Yükleniyor…
İptal
Kaydet