https://forum.pjrc.com/threads/27409-Play-RAW-from-Serial-Flash?p=77666#post77666dds
| @@ -85,6 +85,7 @@ | |||
| #include "play_queue.h" | |||
| #include "play_sd_raw.h" | |||
| #include "play_sd_wav.h" | |||
| #include "play_serialflash_raw.h" | |||
| #include "record_queue.h" | |||
| #include "synth_tonesweep.h" | |||
| #include "synth_sine.h" | |||
| @@ -10,6 +10,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // Create the Audio components. These should be created in the | |||
| // order data flows, inputs/sources -> processing -> outputs | |||
| @@ -14,6 +14,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // Create the Audio components. These should be created in the | |||
| // order data flows, inputs/sources -> processing -> outputs | |||
| @@ -15,6 +15,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| //const int myInput = AUDIO_INPUT_MIC; | |||
| @@ -13,6 +13,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputAnalog adc1; //xy=164,95 | |||
| @@ -7,6 +7,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| // const int myInput = AUDIO_INPUT_MIC; | |||
| @@ -3,6 +3,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputI2S i2s1; //xy=139,91 | |||
| @@ -50,6 +50,7 @@ many blocks you provided with AudioMemory(). | |||
| #include <Wire.h> | |||
| #include <SD.h> | |||
| #include <SPI.h> | |||
| #include <SerialFlash.h> | |||
| #include <Bounce.h> | |||
| @@ -13,6 +13,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioSynthWaveformSine sine1; //xy=158,74 | |||
| @@ -2,6 +2,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputI2S i2s1; //xy=99,60 | |||
| @@ -25,6 +25,7 @@ The audio board uses the following pins. | |||
| #include <Wire.h> | |||
| #include <SD.h> | |||
| #include <SPI.h> | |||
| #include <SerialFlash.h> | |||
| #include <Bounce.h> | |||
| #include "filters.h" | |||
| @@ -51,6 +51,7 @@ many blocks you provided with AudioMemory(). | |||
| #include <Wire.h> | |||
| #include <SD.h> | |||
| #include <SPI.h> | |||
| #include <SerialFlash.h> | |||
| #include <Bounce.h> | |||
| // Number of samples in each delay line | |||
| @@ -9,6 +9,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputAnalog adc1; //xy=161,80 | |||
| @@ -9,6 +9,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputI2S i2s1; //xy=200,69 | |||
| @@ -6,6 +6,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| // const int myInput = AUDIO_INPUT_MIC; | |||
| @@ -7,6 +7,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| @@ -7,6 +7,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| // const int myInput = AUDIO_INPUT_MIC; | |||
| @@ -7,6 +7,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| @@ -7,6 +7,7 @@ This example code is in the public domain | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| @@ -26,6 +26,7 @@ The audio board uses the following pins. | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| #include <Bounce.h> | |||
| AudioSynthToneSweep myEffect; | |||
| @@ -23,6 +23,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioSynthWaveform waveform1; //xy=110,75 | |||
| @@ -17,6 +17,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioSynthWaveformSine sine1; //xy=125,221 | |||
| @@ -15,6 +15,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputI2S i2s2; //xy=105,63 | |||
| @@ -2,6 +2,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| #include <Bounce.h> | |||
| // WAV files converted to code by wav2sketch | |||
| @@ -9,6 +9,7 @@ | |||
| #include <Wire.h> | |||
| #include <SD.h> | |||
| #include <SPI.h> | |||
| #include <SerialFlash.h> | |||
| #include "PlaySynthMusic.h" | |||
| @@ -5,6 +5,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioSynthWaveform waveform1; //xy=188,240 | |||
| @@ -29,6 +29,7 @@ | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| #include <SerialFlash.h> | |||
| AudioPlaySdWav playWav1; | |||
| // Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC | |||
| @@ -549,7 +549,7 @@ | |||
| <h3>Summary</h3> | |||
| <p>Play a short sound clip, stored directly in memory. | |||
| 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> | |||
| <h3>Audio Connections</h3> | |||
| <table class=doc align=center cellpadding=3> | |||
| @@ -599,7 +599,7 @@ | |||
| <script type="text/javascript"> | |||
| RED.nodes.registerType('AudioPlaySdWav',{ | |||
| shortName: "playWav", | |||
| shortName: "playSdWav", | |||
| inputs:0, | |||
| outputs:2, | |||
| category: 'play-function', | |||
| @@ -672,7 +672,7 @@ | |||
| <script type="text/javascript"> | |||
| RED.nodes.registerType('AudioPlaySdRaw',{ | |||
| shortName: "playRaw", | |||
| shortName: "playSdRaw", | |||
| inputs:0, | |||
| outputs:1, | |||
| category: 'play-function', | |||
| @@ -734,6 +734,73 @@ | |||
| </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"> | |||
| RED.nodes.registerType('AudioPlayQueue',{ | |||
| @@ -0,0 +1,112 @@ | |||
| /* 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; | |||
| } | |||
| @@ -0,0 +1,52 @@ | |||
| /* 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 | |||