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 |