https://forum.pjrc.com/threads/27409-Play-RAW-from-Serial-Flash?p=77666#post77666dds
#include "play_queue.h" | #include "play_queue.h" | ||||
#include "play_sd_raw.h" | #include "play_sd_raw.h" | ||||
#include "play_sd_wav.h" | #include "play_sd_wav.h" | ||||
#include "play_serialflash_raw.h" | |||||
#include "record_queue.h" | #include "record_queue.h" | ||||
#include "synth_tonesweep.h" | #include "synth_tonesweep.h" | ||||
#include "synth_sine.h" | #include "synth_sine.h" |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// Create the Audio components. These should be created in the | // Create the Audio components. These should be created in the | ||||
// order data flows, inputs/sources -> processing -> outputs | // order data flows, inputs/sources -> processing -> outputs |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// Create the Audio components. These should be created in the | // Create the Audio components. These should be created in the | ||||
// order data flows, inputs/sources -> processing -> outputs | // order data flows, inputs/sources -> processing -> outputs |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; | ||||
//const int myInput = AUDIO_INPUT_MIC; | //const int myInput = AUDIO_INPUT_MIC; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputAnalog adc1; //xy=164,95 | AudioInputAnalog adc1; //xy=164,95 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; | ||||
// const int myInput = AUDIO_INPUT_MIC; | // const int myInput = AUDIO_INPUT_MIC; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputI2S i2s1; //xy=139,91 | AudioInputI2S i2s1; //xy=139,91 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SerialFlash.h> | |||||
#include <Bounce.h> | #include <Bounce.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioSynthWaveformSine sine1; //xy=158,74 | AudioSynthWaveformSine sine1; //xy=158,74 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputI2S i2s1; //xy=99,60 | AudioInputI2S i2s1; //xy=99,60 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SerialFlash.h> | |||||
#include <Bounce.h> | #include <Bounce.h> | ||||
#include "filters.h" | #include "filters.h" | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SerialFlash.h> | |||||
#include <Bounce.h> | #include <Bounce.h> | ||||
// Number of samples in each delay line | // Number of samples in each delay line |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputAnalog adc1; //xy=161,80 | AudioInputAnalog adc1; //xy=161,80 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputI2S i2s1; //xy=200,69 | AudioInputI2S i2s1; //xy=200,69 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; | ||||
// const int myInput = AUDIO_INPUT_MIC; | // const int myInput = AUDIO_INPUT_MIC; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; | ||||
// const int myInput = AUDIO_INPUT_MIC; | // const int myInput = AUDIO_INPUT_MIC; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
const int myInput = AUDIO_INPUT_LINEIN; | const int myInput = AUDIO_INPUT_LINEIN; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
#include <Bounce.h> | #include <Bounce.h> | ||||
AudioSynthToneSweep myEffect; | AudioSynthToneSweep myEffect; |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioSynthWaveform waveform1; //xy=110,75 | AudioSynthWaveform waveform1; //xy=110,75 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioSynthWaveformSine sine1; //xy=125,221 | AudioSynthWaveformSine sine1; //xy=125,221 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioInputI2S i2s2; //xy=105,63 | AudioInputI2S i2s2; //xy=105,63 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
#include <Bounce.h> | #include <Bounce.h> | ||||
// WAV files converted to code by wav2sketch | // WAV files converted to code by wav2sketch |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SerialFlash.h> | |||||
#include "PlaySynthMusic.h" | #include "PlaySynthMusic.h" | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
// GUItool: begin automatically generated code | // GUItool: begin automatically generated code | ||||
AudioSynthWaveform waveform1; //xy=188,240 | AudioSynthWaveform waveform1; //xy=188,240 |
#include <Wire.h> | #include <Wire.h> | ||||
#include <SPI.h> | #include <SPI.h> | ||||
#include <SD.h> | #include <SD.h> | ||||
#include <SerialFlash.h> | |||||
AudioPlaySdWav playWav1; | AudioPlaySdWav playWav1; | ||||
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC | // Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC |
<h3>Summary</h3> | <h3>Summary</h3> | ||||
<p>Play a short sound clip, stored directly in memory. | <p>Play a short sound clip, stored directly in memory. | ||||
Data files are created with the | Data files are created with the | ||||
<a href="https://github.com/PaulStoffregen/Audio/tree/master/examples/PlayFromSketch/wav2sketch" target="_blank">wav2sketch program</a>, | |||||
<a href="https://github.com/PaulStoffregen/Audio/tree/master/examples/SamplePlayer/wav2sketch" target="_blank">wav2sketch program</a>, | |||||
and copied to the sketch folder to become part of your sketch.</p> | and copied to the sketch folder to become part of your sketch.</p> | ||||
<h3>Audio Connections</h3> | <h3>Audio Connections</h3> | ||||
<table class=doc align=center cellpadding=3> | <table class=doc align=center cellpadding=3> | ||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
RED.nodes.registerType('AudioPlaySdWav',{ | RED.nodes.registerType('AudioPlaySdWav',{ | ||||
shortName: "playWav", | |||||
shortName: "playSdWav", | |||||
inputs:0, | inputs:0, | ||||
outputs:2, | outputs:2, | ||||
category: 'play-function', | category: 'play-function', | ||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
RED.nodes.registerType('AudioPlaySdRaw',{ | RED.nodes.registerType('AudioPlaySdRaw',{ | ||||
shortName: "playRaw", | |||||
shortName: "playSdRaw", | |||||
inputs:0, | inputs:0, | ||||
outputs:1, | outputs:1, | ||||
category: 'play-function', | category: 'play-function', | ||||
</script> | </script> | ||||
<script type="text/javascript"> | |||||
RED.nodes.registerType('AudioPlaySerialflashRaw',{ | |||||
shortName: "playFlashRaw", | |||||
inputs:0, | |||||
outputs:1, | |||||
category: 'play-function', | |||||
color:"#E6E0F8", | |||||
icon: "arrow-in.png" | |||||
}); | |||||
</script> | |||||
<script type="text/x-red" data-help-name="AudioPlaySerialflashRaw"> | |||||
<h3>Summary</h3> | |||||
<div> | |||||
<p>Play a RAW data file, stored on a Serial Flash chip. These chips | |||||
are far more efficient than SD cards, allowing many files to be | |||||
played simultaneously by copies of this object. | |||||
</p> | |||||
<p align=center><img src="w25q128fv.jpg"><br><small>W25Q128FV Serial Flash</small></p> | |||||
</div> | |||||
<h3>Audio Connections</h3> | |||||
<table class=doc align=center cellpadding=3> | |||||
<tr class=top><th>Port</th><th>Purpose</th></tr> | |||||
<tr class=odd><td align=center>Out 0</td><td>Sound Output</td></tr> | |||||
</table> | |||||
<h3>Functions</h3> | |||||
<p class=func><span class=keyword>play</span>(filename);</p> | |||||
<p class=desc>Begin playing a RAW data file. If a file is already playing, | |||||
it is stopped and this file starts playing from the beginning. | |||||
</p> | |||||
<p class=func><span class=keyword>stop</span>();</p> | |||||
<p class=desc>Stop playing. If not playing, this function has no effect. | |||||
</p> | |||||
<p class=func><span class=keyword>isPlaying</span>();</p> | |||||
<p class=desc>Return true (non-zero) if playing, or false (zero) | |||||
when not playing. | |||||
</p> | |||||
<p class=func><span class=keyword>positionMillis</span>();</p> | |||||
<p class=desc>While playing, return the current time offset, in | |||||
milliseconds. When not playing, the return from this function | |||||
is undefined. | |||||
</p> | |||||
<p class=func><span class=keyword>lengthMillis</span>();</p> | |||||
<p class=desc>Return the total length of the current sound clip, | |||||
in milliseconds. When not playing, the return from this function | |||||
is undefined. | |||||
</p> | |||||
<h3>Examples</h3> | |||||
<!--<p class=exam>File > Examples > Audio > Recorder--> | |||||
<p class=exam>TODO: play example needed.... | |||||
</p> | |||||
<p class=exam>File > Examples > SerialFlash > CopyFromSD | |||||
</p> | |||||
<h3>Notes</h3> | |||||
<p>The data file must be RAW 16 bit signed integers in LSB-first format. | |||||
</p> | |||||
<p>The <a href="https://github.com/PaulStoffregen/SerialFlash" target="_blank">SerialFlash library</a> | |||||
is used to access the flash chip. You can also use SerialFlash's functions | |||||
to access the stored files, or add data to the flash chip. | |||||
</p> | |||||
</script> | |||||
<script type="text/x-red" data-template-name="AudioPlaySerialflashRaw"> | |||||
<div class="form-row"> | |||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label> | |||||
<input type="text" id="node-input-name" placeholder="Name"> | |||||
</div> | |||||
</script> | |||||
<script type="text/javascript"> | <script type="text/javascript"> | ||||
RED.nodes.registerType('AudioPlayQueue',{ | RED.nodes.registerType('AudioPlayQueue',{ |
/* Audio Library for Teensy 3.X | |||||
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com | |||||
* Modified to use SerialFlash instead of SD library by Wyatt Olson <wyatt@digitalcave.ca> | |||||
* | |||||
* Development of this audio library was funded by PJRC.COM, LLC by sales of | |||||
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop | |||||
* open source software by purchasing Teensy or other PJRC products. | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to deal | |||||
* in the Software without restriction, including without limitation the rights | |||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
* copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice, development funding notice, and this permission | |||||
* notice shall be included in all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
* THE SOFTWARE. | |||||
*/ | |||||
#include "play_serialflash_raw.h" | |||||
#include "spi_interrupt.h" | |||||
void AudioPlaySerialflashRaw::begin(void) | |||||
{ | |||||
playing = false; | |||||
file_offset = 0; | |||||
file_size = 0; | |||||
} | |||||
bool AudioPlaySerialflashRaw::play(const char *filename) | |||||
{ | |||||
stop(); | |||||
AudioStartUsingSPI(); | |||||
rawfile = SerialFlash.open(filename); | |||||
if (!rawfile) { | |||||
//Serial.println("unable to open file"); | |||||
AudioStopUsingSPI(); | |||||
return false; | |||||
} | |||||
file_size = rawfile.size(); | |||||
file_offset = 0; | |||||
//Serial.println("able to open file"); | |||||
playing = true; | |||||
return true; | |||||
} | |||||
void AudioPlaySerialflashRaw::stop(void) | |||||
{ | |||||
__disable_irq(); | |||||
if (playing) { | |||||
playing = false; | |||||
__enable_irq(); | |||||
rawfile.close(); | |||||
AudioStopUsingSPI(); | |||||
} else { | |||||
__enable_irq(); | |||||
} | |||||
} | |||||
void AudioPlaySerialflashRaw::update(void) | |||||
{ | |||||
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 (rawfile.available()) { | |||||
// we can read more data from the file... | |||||
n = rawfile.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 { | |||||
rawfile.close(); | |||||
AudioStopUsingSPI(); | |||||
playing = false; | |||||
Serial.println("Finished playing sample"); //TODO | |||||
} | |||||
release(block); | |||||
} | |||||
#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 | |||||
uint32_t AudioPlaySerialflashRaw::positionMillis(void) | |||||
{ | |||||
return ((uint64_t)file_offset * B2M) >> 32; | |||||
} | |||||
uint32_t AudioPlaySerialflashRaw::lengthMillis(void) | |||||
{ | |||||
return ((uint64_t)file_size * B2M) >> 32; | |||||
} | |||||
/* Audio Library for Teensy 3.X | |||||
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com | |||||
* Modified to use SerialFlash instead of SD library by Wyatt Olson <wyatt@digitalcave.ca> | |||||
* | |||||
* Development of this audio library was funded by PJRC.COM, LLC by sales of | |||||
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop | |||||
* open source software by purchasing Teensy or other PJRC products. | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to deal | |||||
* in the Software without restriction, including without limitation the rights | |||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
* copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice, development funding notice, and this permission | |||||
* notice shall be included in all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
* THE SOFTWARE. | |||||
*/ | |||||
#ifndef play_serial_raw_h_ | |||||
#define play_serial_raw_h_ | |||||
#include <AudioStream.h> | |||||
#include <SerialFlash.h> | |||||
class AudioPlaySerialflashRaw : public AudioStream | |||||
{ | |||||
public: | |||||
AudioPlaySerialflashRaw(void) : AudioStream(0, NULL) { 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); | |||||
private: | |||||
SerialFlashFile rawfile; | |||||
uint32_t file_size; | |||||
volatile uint32_t file_offset; | |||||
volatile bool playing; | |||||
}; | |||||
#endif |