Aller au contenu


Photo
- - - - -

lecture fichiers sur carte SD


16 réponses à ce sujet

#1 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 05 mars 2023 - 01:30

Bonjour à tous,
voilà mon premier projet avec arduino, j'avoue que je n'y connais pas grand chose mais j'essaie de comprendre en utilisant mes notions de PHP, javascript etc.

Je suis sur un projet qui est presque terminé, c'est une sorte de répondeur qui enregistre les messages sur une carte SD. J'ai un bouton qui me permet de lire les enregistrements mais cela ne lit que le dernier.
En modifiant PlayAllRecordings à la place de PlatLastRecording j'arrive à lire tout mais cela commence par le plus ancien. Or J'aimerai lire plusieurs messages en partant du dernier pour écouter le plus récent dabord donc. Eventuellement choisir une limite par exemple les 5 ou 10 derniers, mais toujours avec le plus récent en premier de façon à écouter dabord celui que l'on vient d'enregistrer.

Donc en gros quand je décroche le combiné, j'appuie sur le bouton lecture, j'entend le message que je viens d'enregistrer, puis le précédent,, puis encore le précédent et ainsi de suite avec une limite queje pourrai remettre à 1 facilement pour n'écouter que le dernier.

J'ai suivi un tuto pour faire tout ça, donc le code n'est pas de moi. J'espère que vous allez pouvoir m'aider car cette fonctionnalité m’intéresse vraiment beaucoup.

Merci par avance à ceux qui me répondront, en espérant qu'une solution simple me permette d'y arriver :)

voici le code:
 

/**
 * Audio Guestbook, Copyright (c) 2022 Playful Technology
 * 
 * Tested using a Teensy 4.0 with Teensy Audio Shield, although should work 
 * with minor modifications on other similar hardware
 * 
 * When handset is lifted, a pre-recorded greeting message is played, followed by a tone.
 * Then, recording starts, and continues until the handset is replaced.
 * Playback button allows all messages currently saved on SD card through earpiece 
 * 
 * Files are saved on SD card as 44.1kHz, 16-bit, mono signed integer RAW audio format 
 * --> changed this to WAV recording, DD4WH 2022_07_31
 * --> added MTP support, which enables copying WAV files from the SD card via the USB connection, DD4WH 2022_08_01
 * 
 * 
 * Frank DD4WH, August 1st 2022 
 * for a DBP 611 telephone (closed contact when handheld is lifted) & with recording to WAV file
 * contact for switch button 0 is closed when handheld is lifted
 * 
 * GNU GPL v3.0 license
 * 
 */

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#include <MTP_Teensy.h>
#include "play_sd_wav.h" // local copy with fixes

// DEFINES
// Define pins used by Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14
// And those used for inputs
#define HOOK_PIN 0
#define PLAYBACK_BUTTON_PIN 1

#define noINSTRUMENT_SD_WRITE

// GLOBALS
// Audio initialisation code can be generated using the GUI interface at https://www.pjrc.com/teensy/gui/
// Inputs
AudioSynthWaveform          waveform1; // To create the "beep" sfx
AudioInputI2S               i2s2; // I2S input from microphone on audio shield
AudioPlaySdWavX              playWav1; // Play 44.1kHz 16-bit PCM greeting WAV file
AudioRecordQueue            queue1; // Creating an audio buffer in memory before saving to SD
AudioMixer4                 mixer; // Allows merging several inputs to same output
AudioOutputI2S              i2s1; // I2S interface to Speaker/Line Out on Audio shield
AudioConnection patchCord1(waveform1, 0, mixer, 0); // wave to mixer 
AudioConnection patchCord3(playWav1, 0, mixer, 1); // wav file playback mixer
AudioConnection patchCord4(mixer, 0, i2s1, 0); // mixer output to speaker (L)
AudioConnection patchCord6(mixer, 0, i2s1, 1); // mixer output to speaker (R)
AudioConnection patchCord5(i2s2, 0, queue1, 0); // mic input to queue (L)
AudioControlSGTL5000      sgtl5000_1;

// Filename to save audio recording on SD card
char filename[15];
// The file object itself
File frec;

// Use long 40ms debounce time on both switches
Bounce buttonRecord = Bounce(HOOK_PIN, 40);
Bounce buttonPlay = Bounce(PLAYBACK_BUTTON_PIN, 40);

// Keep track of current state of the device
enum Mode {Initialising, Ready, Prompting, Recording, Playing};
Mode mode = Mode::Initialising;

float beep_volume = 0.04f; // not too loud :-)

uint32_t MTPcheckInterval; // default value of device check interval [ms]

//Timer
unsigned long startTime = 0;

// variables for writing to WAV file
unsigned long ChunkSize = 0L;
unsigned long Subchunk1Size = 16;
unsigned int AudioFormat = 1;
unsigned int numChannels = 1;
unsigned long sampleRate = 44100;
unsigned int bitsPerSample = 16;
unsigned long byteRate = sampleRate*numChannels*(bitsPerSample/8);// samplerate x channels x (bitspersample / 8)
unsigned int blockAlign = numChannels*bitsPerSample/8;
unsigned long Subchunk2Size = 0L;
unsigned long recByteSaved = 0L;
unsigned long NumSamples = 0L;
byte byte1, byte2, byte3, byte4;


void setup() {

  Serial.begin(9600);
  while (!Serial && millis() < 5000) {
    // wait for serial port to connect.
  }
  Serial.println("Serial set up correctly");
  Serial.printf("Audio block set to %d samples\n",AUDIO_BLOCK_SAMPLES);
  print_mode();
  // Configure the input pins
  pinMode(HOOK_PIN, INPUT_PULLUP);
  pinMode(PLAYBACK_BUTTON_PIN, INPUT_PULLUP);

  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  // Define which input on the audio shield to use (AUDIO_INPUT_LINEIN / AUDIO_INPUT_MIC)
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  //sgtl5000_1.adcHighPassFilterDisable(); //
  sgtl5000_1.volume(0.95);

  mixer.gain(0, 1.0f);
  mixer.gain(1, 1.0f);

  // Play a beep to indicate system is online
  waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
  wait(1000);
  waveform1.amplitude(0);
  delay(1000);

  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) 
  {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
    else Serial.println("SD card correctly initialized");


  // mandatory to begin the MTP session.
    MTP.begin();

  // Add SD Card
//    MTP.addFilesystem(SD, "SD Card");
    MTP.addFilesystem(SD, "Audio guestbook"); // choose a nice name for the SD card volume to appear in your file explorer
    Serial.println("Added SD card via MTP");
    MTPcheckInterval = MTP.storage()->get_DeltaDeviceCheckTimeMS();
    
    // Value in dB
//  sgtl5000_1.micGain(15);
  sgtl5000_1.micGain(20); // much lower gain is required for the AOM5024 electret capsule

  // Synchronise the Time object used in the program code with the RTC time provider.
  // See https://github.com/PaulStoffregen/Time
  setSyncProvider(getTeensy3Time);
  
  // Define a callback that will assign the correct datetime for any file system operations
  // (i.e. saving a new audio recording onto the SD card)
  FsDateTime::setCallback(dateTime);

  mode = Mode::Ready; print_mode();
}

void loop() {
  // First, read the buttons
  buttonRecord.update();
  buttonPlay.update();

  switch(mode){
    case Mode::Ready:
      // Falling edge occurs when the handset is lifted --> 611 telephone
      if (buttonRecord.fallingEdge()) {
        Serial.println("Handset lifted");
        mode = Mode::Prompting; print_mode();
      }
      else if(buttonPlay.fallingEdge()) {
        //playAllRecordings();
        playAllRecordings();
      }
      break;

    case Mode::Prompting:
      // Wait a second for users to put the handset to their ear
      wait(1000);
      // Play the greeting inviting them to record their message
      playWav1.play("greeting.wav");    
      // Wait until the  message has finished playing
//      while (playWav1.isPlaying()) {
      while (!playWav1.isStopped()) {
        // Check whether the handset is replaced
        buttonRecord.update();
        buttonPlay.update();
        // Handset is replaced
        if(buttonRecord.risingEdge()) {
          playWav1.stop();
          mode = Mode::Ready; print_mode();
          return;
        }
        if(buttonPlay.fallingEdge()) {
          playWav1.stop();
          //playAllRecordings();
          playAllRecordings();
          return;
        }
        
      }
      // Debug message
      Serial.println("Starting Recording");
      // Play the tone sound effect
      waveform1.begin(beep_volume, 440, WAVEFORM_SINE);
      wait(1250);
      waveform1.amplitude(0);
      // Start the recording function
      startRecording();
      //Timer
      startTime = millis();
      break;

    case Mode::Recording:
      // Handset is replaced
      if(buttonRecord.risingEdge() || millis() - startTime >= 120000) {
        // Debug log
        Serial.println("Stopping Recording");
        // Stop recording
        stopRecording();
        // Play audio tone to confirm recording has ended
        end_Beep();
      }
      else {
        continueRecording();
      }
      break;

    case Mode::Playing: // to make compiler happy
      break;  

    case Mode::Initialising: // to make compiler happy
      break;  
  }   
  
  MTP.loop();  // This is mandatory to be placed in the loop code.
}

void setMTPdeviceChecks(bool nable)
{
  if (nable)
  {
    MTP.storage()->set_DeltaDeviceCheckTimeMS(MTPcheckInterval);
    Serial.print("En");
  }
  else
  {
    MTP.storage()->set_DeltaDeviceCheckTimeMS((uint32_t) -1);
    Serial.print("Dis");
  }
  Serial.println("abled MTP storage device checks");
}
  

#if defined(INSTRUMENT_SD_WRITE)
static uint32_t worstSDwrite, printNext;
#endif // defined(INSTRUMENT_SD_WRITE)

void startRecording() {
  setMTPdeviceChecks(false); // disable MTP device checks while recording
#if defined(INSTRUMENT_SD_WRITE)
  worstSDwrite = 0;
  printNext = 0;
#endif // defined(INSTRUMENT_SD_WRITE)
  // Find the first available file number
//  for (uint8_t i=0; i<9999; i++) { // BUGFIX uint8_t overflows if it reaches 255  
  for (uint16_t i=0; i<99990; i++) {   
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // Create if does not exist, do not open existing, write, sync after write
    if (!SD.exists(filename)) {
      break;
    }
  }
  frec = SD.open(filename, FILE_WRITE);
  Serial.println("Opened file !");
  if(frec) {
    Serial.print("Recording to ");
    Serial.println(filename);
    queue1.begin();
    mode = Mode::Recording; print_mode();
    recByteSaved = 0L;
  }
  else {
    Serial.println("Couldn't open file to record!");
  }
}

void continueRecording() {
#if defined(INSTRUMENT_SD_WRITE)
  uint32_t started = micros();
#endif // defined(INSTRUMENT_SD_WRITE)
#define NBLOX 16  
  // Check if there is data in the queue
  if (queue1.available() >= NBLOX) {
    byte buffer[NBLOX*AUDIO_BLOCK_SAMPLES*sizeof(int16_t)];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    for (int i=0;i<NBLOX;i++)
    {
      memcpy(buffer+i*AUDIO_BLOCK_SAMPLES*sizeof(int16_t), queue1.readBuffer(), AUDIO_BLOCK_SAMPLES*sizeof(int16_t));
      queue1.freeBuffer();
    }
    // Write all 512 bytes to the SD card
    frec.write(buffer, sizeof buffer);
    recByteSaved += sizeof buffer;
  }
  
#if defined(INSTRUMENT_SD_WRITE)
  started = micros() - started;
  if (started > worstSDwrite)
    worstSDwrite = started;

  if (millis() >= printNext)
  {
    Serial.printf("Worst write took %luus\n",worstSDwrite);
    worstSDwrite = 0;
    printNext = millis()+250;
  }
#endif // defined(INSTRUMENT_SD_WRITE)
}

void stopRecording() {
  // Stop adding any new data to the queue
  queue1.end();
  // Flush all existing remaining data from the queue
  while (queue1.available() > 0) {
    // Save to open file
    frec.write((byte*)queue1.readBuffer(), AUDIO_BLOCK_SAMPLES*sizeof(int16_t));
    queue1.freeBuffer();
    recByteSaved += AUDIO_BLOCK_SAMPLES*sizeof(int16_t);
  }
  writeOutHeader();
  // Close the file
  frec.close();
  Serial.println("Closed file");
  mode = Mode::Ready; print_mode();
  setMTPdeviceChecks(true); // enable MTP device checks, recording is finished
}


void playAllRecordings() {
  // Recording files are saved in the root directory
 wait(2000);
  File dir = SD.open("/");
  
  while (true) {
    File entry =  dir.openNextFile();
    if (strstr(entry.name(), "greeting"))
    {
       entry =  dir.openNextFile();
    }
    if (!entry) {
      // no more files
      entry.close();
      end_Beep();
      break;
    }
    //int8_t len = strlen(entry.name()) - 4;
//    if (strstr(strlwr(entry.name() + (len - 4)), ".raw")) {
//    if (strstr(strlwr(entry.name() + (len - 4)), ".wav")) {
    // the lines above throw a warning, so I replace them with this (which is also easier to read):
    if (strstr(entry.name(), ".wav") || strstr(entry.name(), ".WAV")) {
      Serial.print("Now playing ");
      Serial.println(entry.name());
      // Play a short beep before each message
      waveform1.amplitude(beep_volume);
      wait(750);
      waveform1.amplitude(0);
      // Play the file
      playWav1.play(entry.name());
      mode = Mode::Playing; print_mode();
    }
    entry.close();

//    while (playWav1.isPlaying()) { // strangely enough, this works for playRaw, but it does not work properly for playWav
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
//      if(buttonPlay.risingEdge() || buttonRecord.risingEdge()) { // FIX
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge()) { 
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
  }
  // All files have been played
  mode = Mode::Ready; print_mode();
}

void playLastRecording() {
  // Find the first available file number
  uint16_t idx = 0; 
  for (uint16_t i=0; i<9999; i++) {
    // Format the counter as a five-digit number with leading zeroes, followed by file extension
    snprintf(filename, 11, " %05d.wav", i);
    // check, if file with index i exists
    if (!SD.exists(filename)) {
     idx = i - 1;
     break;
      }
  }
      // now play file with index idx == last recorded file
      snprintf(filename, 11, " %05d.wav", idx);
      Serial.println(filename);
      playWav1.play(filename);
      mode = Mode::Playing; print_mode();
      while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
//      if(buttonPlay.risingEdge() || buttonRecord.risingEdge()) { // FIX
      if(buttonPlay.fallingEdge() || buttonRecord.risingEdge()) {
        playWav1.stop();
        mode = Mode::Ready; print_mode();
        return;
      }   
    }
      // file has been played
  mode = Mode::Ready; print_mode();  
  end_Beep();
}


// Retrieve the current time from Teensy built-in RTC
time_t getTeensy3Time(){
  return Teensy3Clock.get();
}

// Callback to assign timestamps for file system operations
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {

  // Return date using FS_DATE macro to format fields.
  *date = FS_DATE(year(), month(), day());

  // Return time using FS_TIME macro to format fields.
  *time = FS_TIME(hour(), minute(), second());

  // Return low time bits in units of 10 ms.
  *ms10 = second() & 1 ? 100 : 0;
}

// Non-blocking delay, which pauses execution of main program logic,
// but while still listening for input 
void wait(unsigned int milliseconds) {
  elapsedMillis msec=0;

  while (msec <= milliseconds) {
    buttonRecord.update();
    buttonPlay.update();
    if (buttonRecord.fallingEdge()) Serial.println("Button (pin 0) Press");
    if (buttonPlay.fallingEdge()) Serial.println("Button (pin 1) Press");
    if (buttonRecord.risingEdge()) Serial.println("Button (pin 0) Release");
    if (buttonPlay.risingEdge()) Serial.println("Button (pin 1) Release");
  }
}


void writeOutHeader() { // update WAV header with final filesize/datasize

//  NumSamples = (recByteSaved*8)/bitsPerSample/numChannels;
//  Subchunk2Size = NumSamples*numChannels*bitsPerSample/8; // number of samples x number of channels x number of bytes per sample
  Subchunk2Size = recByteSaved - 42; // because we didn't make space for the header to start with! Lose 21 samples...
  ChunkSize = Subchunk2Size + 34; // was 36;
  frec.seek(0);
  frec.write("RIFF");
  byte1 = ChunkSize & 0xff;
  byte2 = (ChunkSize >> 8) & 0xff;
  byte3 = (ChunkSize >> 16) & 0xff;
  byte4 = (ChunkSize >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  frec.write("WAVE");
  frec.write("fmt ");
  byte1 = Subchunk1Size & 0xff;
  byte2 = (Subchunk1Size >> 8) & 0xff;
  byte3 = (Subchunk1Size >> 16) & 0xff;
  byte4 = (Subchunk1Size >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = AudioFormat & 0xff;
  byte2 = (AudioFormat >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = numChannels & 0xff;
  byte2 = (numChannels >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = sampleRate & 0xff;
  byte2 = (sampleRate >> 8) & 0xff;
  byte3 = (sampleRate >> 16) & 0xff;
  byte4 = (sampleRate >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = byteRate & 0xff;
  byte2 = (byteRate >> 8) & 0xff;
  byte3 = (byteRate >> 16) & 0xff;
  byte4 = (byteRate >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  byte1 = blockAlign & 0xff;
  byte2 = (blockAlign >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  byte1 = bitsPerSample & 0xff;
  byte2 = (bitsPerSample >> 8) & 0xff;
  frec.write(byte1);  frec.write(byte2); 
  frec.write("data");
  byte1 = Subchunk2Size & 0xff;
  byte2 = (Subchunk2Size >> 8) & 0xff;
  byte3 = (Subchunk2Size >> 16) & 0xff;
  byte4 = (Subchunk2Size >> 24) & 0xff;  
  frec.write(byte1);  frec.write(byte2);  frec.write(byte3);  frec.write(byte4);
  frec.close();
  Serial.println("header written"); 
  Serial.print("Subchunk2: "); 
  Serial.println(Subchunk2Size); 
}

void end_Beep(void) {
          waveform1.frequency(523.25);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
        wait(250);
        waveform1.amplitude(beep_volume);
        wait(250);
        waveform1.amplitude(0);
}

void print_mode(void) { // only for debugging
  Serial.print("Mode switched to: ");
  // Initialising, Ready, Prompting, Recording, Playing
  if(mode == Mode::Ready)           Serial.println(" Ready");
  else if(mode == Mode::Prompting)  Serial.println(" Prompting");
  else if(mode == Mode::Recording)  Serial.println(" Recording");
  else if(mode == Mode::Playing)    Serial.println(" Playing");
  else if(mode == Mode::Initialising)  Serial.println(" Initialising");
  else Serial.println(" Undefined");
}


#2 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 05 mars 2023 - 01:32

j'ai oublé de précider le contenu des fichiers play_sd_wav.cpp:
 

/* Audio Library for Teensy 3.X
 * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
 *
 * 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 <Arduino.h>
#include "play_sd_wav.h"
#include "spi_interrupt.h"


#define STATE_DIRECT_8BIT_MONO        0  // playing mono at native sample rate
#define STATE_DIRECT_8BIT_STEREO    1  // playing stereo at native sample rate
#define STATE_DIRECT_16BIT_MONO        2  // playing mono at native sample rate
#define STATE_DIRECT_16BIT_STEREO    3  // playing stereo at native sample rate
#define STATE_CONVERT_8BIT_MONO        4  // playing mono, converting sample rate
#define STATE_CONVERT_8BIT_STEREO    5  // playing stereo, converting sample rate
#define STATE_CONVERT_16BIT_MONO    6  // playing mono, converting sample rate
#define STATE_CONVERT_16BIT_STEREO    7  // playing stereo, converting sample rate
#define STATE_PARSE1            8  // looking for 20 byte ID header
#define STATE_PARSE2            9  // looking for 16 byte format header
#define STATE_PARSE3            10 // looking for 8 byte data header
#define STATE_PARSE4            11 // ignoring unknown chunk after "fmt "
#define STATE_PARSE5            12 // ignoring unknown chunk before "fmt "
#define STATE_PAUSED            13
#define STATE_STOP            14

void AudioPlaySdWavX::begin(void)
{
    state = STATE_STOP;
    state_play = STATE_STOP;
    data_length = 0;
    if (block_left) {
        release(block_left);
        block_left = NULL;
    }
    if (block_right) {
        release(block_right);
        block_right = NULL;
    }
}


bool AudioPlaySdWavX::play(const char *filename)
{
    stop();
    bool irq = false;
    if (NVIC_IS_ENABLED(IRQ_SOFTWARE)) {
        NVIC_DISABLE_IRQ(IRQ_SOFTWARE);
        irq = true;
    }
#if defined(HAS_KINETIS_SDHC)
    if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStartUsingSPI();
#else
    AudioStartUsingSPI();
#endif
    wavfile = SD.open(filename);
    if (!wavfile) {
#if defined(HAS_KINETIS_SDHC)
        if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI();
#else
        AudioStopUsingSPI();
#endif
        if (irq) NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
        return false;
    }
    buffer_length = 0;
    buffer_offset = 0;
    state_play = STATE_STOP;
    data_length = 20;
    header_offset = 0;
    state = STATE_PARSE1;
    if (irq) NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
    return true;
}

void AudioPlaySdWavX::stop(void)
{
    bool irq = false;
    if (NVIC_IS_ENABLED(IRQ_SOFTWARE)) {
        NVIC_DISABLE_IRQ(IRQ_SOFTWARE);
        irq = true;
    }
    if (state != STATE_STOP) {
        audio_block_t *b1 = block_left;
        block_left = NULL;
        audio_block_t *b2 = block_right;
        block_right = NULL;
        state = STATE_STOP;
        if (b1) release(b1);
        if (b2) release(b2);
        wavfile.close();
#if defined(HAS_KINETIS_SDHC)
        if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI();
#else
        AudioStopUsingSPI();
#endif
    }
    if (irq) NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
}

void AudioPlaySdWavX::togglePlayPause(void) {
    // take no action if wave header is not parsed OR
    // state is explicitly STATE_STOP
    if(state_play >= 8 || state == STATE_STOP) return;

    // toggle back and forth between state_play and STATE_PAUSED
    if(state == state_play) {
        state = STATE_PAUSED;
    }
    else if(state == STATE_PAUSED) {
        state = state_play;
    }
}

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

    // only update if we're playing and not paused
    if (state == STATE_STOP || state == STATE_PAUSED) return;

    // allocate the audio blocks to transmit
    block_left = allocate();
    if (block_left == NULL) return;
    if (state < 8 && (state & 1) == 1) {
        // if we're playing stereo, allocate another
        // block for the right channel output
        block_right = allocate();
        if (block_right == NULL) {
            release(block_left);
            return;
        }
    } else {
        // if we're playing mono or just parsing
        // the WAV file header, no right-side block
        block_right = NULL;
    }
    block_offset = 0;

    //Serial.println("update");

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

    // we only get to this point when buffer[] is empty
    if (state != STATE_STOP && wavfile.available()) {
        // we can read more data from the file...
        readagain:
        buffer_length = wavfile.read(buffer, sizeof buffer);
        if (buffer_length == 0) goto end;
        buffer_offset = 0;
        bool parsing = (state >= 8);
        bool txok = consume(buffer_length);
        if (txok) {
            if (state != STATE_STOP) return;
        } else {
            if (state != STATE_STOP) {
                if (parsing && state < 8) goto readagain;
                else goto cleanup;
            }
        }
    }
end:    // end of file reached or other reason to stop
    wavfile.close();
#if defined(HAS_KINETIS_SDHC)
    if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI();
#else
    AudioStopUsingSPI();
#endif
    state_play = STATE_STOP;
    state = STATE_STOP;
cleanup:
    if (block_left) {
        if (block_offset > 0) {
            for (uint32_t i=block_offset; i < AUDIO_BLOCK_SAMPLES; i++) {
                block_left->data[i] = 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) {
            for (uint32_t i=block_offset; i < AUDIO_BLOCK_SAMPLES; i++) {
                block_right->data[i] = 0;
            }
            transmit(block_right, 1);
        }
        release(block_right);
        block_right = NULL;
    }
}


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

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

    p = buffer + buffer_offset;
start:
    if (size == 0) return false;
#if 0
    Serial.print("AudioPlaySdWavX consume, ");
    Serial.print("size = ");
    Serial.print(size);
    Serial.print(", buffer_offset = ");
    Serial.print(buffer_offset);
    Serial.print(", data_length = ");
    Serial.print(data_length);
    Serial.print(", space = ");
    Serial.print((AUDIO_BLOCK_SAMPLES - block_offset) * 2);
    Serial.print(", state = ");
    Serial.println(state);
#endif
    switch (state) {
      // parse wav file header, is this really a .wav file?
      case STATE_PARSE1:
        len = data_length;
        if (size < len) len = size;
        memcpy((uint8_t *)header + header_offset, p, len);
        header_offset += len;
        buffer_offset += len;
        data_length -= len;
        if (data_length > 0) return false;
        // parse the header...
        if (header[0] == 0x46464952 && header[2] == 0x45564157) {
            //Serial.println("is wav file");
            if (header[3] == 0x20746D66) {
                // "fmt " header
                if (header[4] < 16) {
                    // WAV "fmt " info must be at least 16 bytes
                    break;
                }
                if (header[4] > sizeof(header)) {
                    // if such .wav files exist, increasing the
                    // size of header[] should accomodate them...
                    //Serial.println("WAVEFORMATEXTENSIBLE too long");
                    break;
                }
                //Serial.println("header ok");
                header_offset = 0;
                state = STATE_PARSE2;
            } else {
                // first chuck is something other than "fmt "
                //Serial.print("skipping \"");
                //Serial.printf("\" (%08X), ", __builtin_bswap32(header[3]));
                //Serial.print(header[4]);
                //Serial.println(" bytes");
                header_offset = 12;
                state = STATE_PARSE5;
            }
            p += len;
            size -= len;
            data_length = header[4];
            goto start;
        }
        //Serial.println("unknown WAV header");
        break;

      // check & extract key audio parameters
      case STATE_PARSE2:
        len = data_length;
        if (size < len) len = size;
        memcpy((uint8_t *)header + header_offset, p, len);
        header_offset += len;
        buffer_offset += len;
        data_length -= len;
        if (data_length > 0) return false;
        if (parse_format()) {
            //Serial.println("audio format ok");
            p += len;
            size -= len;
            data_length = 8;
            header_offset = 0;
            state = STATE_PARSE3;
            goto start;
        }
        //Serial.println("unknown audio format");
        break;

      // find the data chunk
      case STATE_PARSE3: // 10
        len = data_length;
        if (size < len) len = size;
        memcpy((uint8_t *)header + header_offset, p, len);
        header_offset += len;
        buffer_offset += len;
        data_length -= len;
        if (data_length > 0) return false;
        //Serial.print("chunk id = ");
        //Serial.print(header[0], HEX);
        //Serial.print(", length = ");
        //Serial.println(header[1]);
        p += len;
        size -= len;
        data_length = header[1];
        if (header[0] == 0x61746164) {
            //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.
            leftover_bytes = 0;
            state = state_play;
            if (state & 1) {
                // if we're going to start stereo
                // better allocate another output block
                block_right = allocate();
                if (!block_right) return false;
            }
            total_length = data_length;
        } else {
            state = STATE_PARSE4;
        }
        goto start;

      // ignore any extra unknown chunks (title & artist info)
      case STATE_PARSE4: // 11
        if (size < data_length) {
            data_length -= size;
            buffer_offset += size;
            return false;
        }
        p += data_length;
        size -= data_length;
        buffer_offset += data_length;
        data_length = 8;
        header_offset = 0;
        state = STATE_PARSE3;
        //Serial.println("consumed unknown chunk");
        goto start;

      // skip past "junk" data before "fmt " header
      case STATE_PARSE5:
        len = data_length;
        if (size < len) len = size;
        buffer_offset += len;
        data_length -= len;
        if (data_length > 0) return false;
        p += len;
        size -= len;
        data_length = 8;
        state = STATE_PARSE1;
        goto start;

      // playing mono at native sample rate
      case STATE_DIRECT_8BIT_MONO:
        return false;

      // playing stereo at native sample rate
      case STATE_DIRECT_8BIT_STEREO:
        return false;

      // playing mono at native sample rate
      case STATE_DIRECT_16BIT_MONO:
        if (size > data_length) size = data_length;
        data_length -= size;
        while (1) {
            lsb = *p++;
            msb = *p++;
            size -= 2;
            block_left->data[block_offset++] = (msb << 8) | lsb;
            if (block_offset >= AUDIO_BLOCK_SAMPLES) {
                transmit(block_left, 0);
                transmit(block_left, 1);
                release(block_left);
                block_left = NULL;
                data_length += size;
                buffer_offset = p - buffer;
                if (block_right) release(block_right);
                if (data_length == 0) state = STATE_STOP;
                return true;
            }
            if (size == 0) {
                if (data_length == 0) break;
                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
        }
        state = STATE_STOP;
        return false;

      // playing stereo at native sample rate
      case STATE_DIRECT_16BIT_STEREO:
        if (size > data_length) size = data_length;
        data_length -= size;
        if (leftover_bytes) {
            block_left->data[block_offset] = header[0];
//PAH fix problem with left+right channels being swapped
            leftover_bytes = 0;
            goto right16;
        }
        while (1) {
            lsb = *p++;
            msb = *p++;
            size -= 2;
            if (size == 0) {
                if (data_length == 0) break;
                header[0] = (msb << 8) | lsb;
                leftover_bytes = 2;
                return false;
            }
            block_left->data[block_offset] = (msb << 8) | lsb;
            right16:
            lsb = *p++;
            msb = *p++;
            size -= 2;
            block_right->data[block_offset++] = (msb << 8) | lsb;
            if (block_offset >= AUDIO_BLOCK_SAMPLES) {
                transmit(block_left, 0);
                release(block_left);
                block_left = NULL;
                transmit(block_right, 1);
                release(block_right);
                block_right = NULL;
                data_length += size;
                buffer_offset = p - buffer;
                if (data_length == 0) state = STATE_STOP;
                return true;
            }
            if (size == 0) {
                if (data_length == 0) break;
                leftover_bytes = 0;
                return false;
            }
        }
        // end of file reached
        if (block_offset > 0) {
            // TODO: fill remainder of last block with zero and transmit
        }
        state = STATE_STOP;
        return false;

      // playing mono, converting sample rate
      case STATE_CONVERT_8BIT_MONO :
        return false;

      // playing stereo, converting sample rate
      case STATE_CONVERT_8BIT_STEREO:
        return false;

      // playing mono, converting sample rate
      case STATE_CONVERT_16BIT_MONO:
        return false;

      // playing stereo, converting sample rate
      case STATE_CONVERT_16BIT_STEREO:
        return false;

      // ignore any extra data after playing
      // or anything following any error
      case STATE_STOP:
        return false;

      // this is not supposed to happen!
      //default:
        //Serial.println("AudioPlaySdWavX, unknown state");
    }
    state_play = STATE_STOP;
    state = STATE_STOP;
    return false;
}


/*
00000000  52494646 66EA6903 57415645 666D7420  RIFFf.i.WAVEfmt
00000010  10000000 01000200 44AC0000 10B10200  ........D.......
00000020  04001000 4C495354 3A000000 494E464F  ....LIST:...INFO
00000030  494E414D 14000000 49205761 6E742054  INAM....I Want T
00000040  6F20436F 6D65204F 76657200 49415254  o Come Over.IART
00000050  12000000 4D656C69 73736120 45746865  ....Melissa Ethe
00000060  72696467 65006461 746100EA 69030100  ridge.data..i...
00000070  FEFF0300 FCFF0400 FDFF0200 0000FEFF  ................
00000080  0300FDFF 0200FFFF 00000100 FEFF0300  ................
00000090  FDFF0300 FDFF0200 FFFF0100 0000FFFF  ................
*/





// SD library on Teensy3 at 96 MHz
//  256 byte chunks, speed is 443272 bytes/sec
//  512 byte chunks, speed is 468023 bytes/sec

#define B2M_44100 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT) // 97352592
#define B2M_22050 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT * 2.0)
#define B2M_11025 (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT * 4.0)

bool AudioPlaySdWavX::parse_format(void)
{
    uint8_t num = 0;
    uint16_t format;
    uint16_t channels;
    uint32_t rate, b2m;
    uint16_t bits;

    format = header[0];
    //Serial.print("  format = ");
    //Serial.println(format);
    if (format != 1) return false;

    rate = header[1];
    //Serial.print("  rate = ");
    //Serial.println(rate);
    if (rate == 44100) {
        b2m = B2M_44100;
    } else if (rate == 22050) {
        b2m = B2M_22050;
        num |= 4;
    } else if (rate == 11025) {
        b2m = B2M_11025;
        num |= 4;
    } else {
        return false;
    }

    channels = header[0] >> 16;
    //Serial.print("  channels = ");
    //Serial.println(channels);
    if (channels == 1) {
    } else if (channels == 2) {
        b2m >>= 1;
        num |= 1;
    } else {
        return false;
    }

    bits = header[3] >> 16;
    //Serial.print("  bits = ");
    //Serial.println(bits);
    if (bits == 8) {
    } else if (bits == 16) {
        b2m >>= 1;
        num |= 2;
    } else {
        return false;
    }

    bytes2millis = b2m;
    //Serial.print("  bytes2millis = ");
    //Serial.println(b2m);

    // we're not checking the byte rate and block align fields
    // if they're not the expected values, all we could do is
    // return false.  Do any real wav files have unexpected
    // values in these other fields?
    state_play = num;
    return true;
}


bool AudioPlaySdWavX::isPlaying(void)
{
    uint8_t s = *(volatile uint8_t *)&state;
    return (s < 8);
}


bool AudioPlaySdWavX::isPaused(void)
{
    uint8_t s = *(volatile uint8_t *)&state;
    return (s == STATE_PAUSED);
}


bool AudioPlaySdWavX::isStopped(void)
{
    uint8_t s = *(volatile uint8_t *)&state;
    return (s == STATE_STOP);
}


uint32_t AudioPlaySdWavX::positionMillis(void)
{
    uint8_t s = *(volatile uint8_t *)&state;
    if (s >= 8 && s != STATE_PAUSED) return 0;
    uint32_t tlength = *(volatile uint32_t *)&total_length;
    uint32_t dlength = *(volatile uint32_t *)&data_length;
    uint32_t offset = tlength - dlength;
    uint32_t b2m = *(volatile uint32_t *)&bytes2millis;
    return ((uint64_t)offset * b2m) >> 32;
}


uint32_t AudioPlaySdWavX::lengthMillis(void)
{
    uint8_t s = *(volatile uint8_t *)&state;
    if (s >= 8 && s != STATE_PAUSED) return 0;
    uint32_t tlength = *(volatile uint32_t *)&total_length;
    uint32_t b2m = *(volatile uint32_t *)&bytes2millis;
    return ((uint64_t)tlength * b2m) >> 32;
}


#3 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 05 mars 2023 - 01:33

et le play_sd_wav.h
 

/* Audio Library for Teensy 3.X
 * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
 *
 * 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_sd_wavx_h_
#define play_sd_wavx_h_

#include "Arduino.h"
#include "AudioStream.h"
#include "SD.h"

class AudioPlaySdWavX : public AudioStream
{
public:
    AudioPlaySdWavX(void) : AudioStream(0, NULL), block_left(NULL), block_right(NULL) { begin(); }
    void begin(void);
    bool play(const char *filename);
    void togglePlayPause(void);
    void stop(void);
    bool isPlaying(void);
    bool isPaused(void);
    bool isStopped(void);
    uint32_t positionMillis(void);
    uint32_t lengthMillis(void);
    virtual void update(void);
private:
    File wavfile;
    bool consume(uint32_t size);
    bool parse_format(void);
    uint32_t header[10];        // temporary storage of wav header data
    uint32_t data_length;        // number of bytes remaining in current section
    uint32_t total_length;        // number of audio data bytes in file
    uint32_t bytes2millis;
    audio_block_t *block_left;
    audio_block_t *block_right;
    uint16_t block_offset;        // how much data is in block_left & block_right
    uint8_t buffer[AUDIO_BLOCK_SAMPLES*sizeof(int16_t)*2];        // buffer two blocks of data
    uint16_t buffer_offset;        // where we're at consuming "buffer"
    uint16_t buffer_length;        // how much data is in "buffer"
    uint8_t header_offset;        // number of bytes in header[]
    uint8_t state;
    uint8_t state_play;
    uint8_t leftover_bytes;
};

#endif


#4 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 07 mars 2023 - 12:17



void playLastRecordings(uint8_t n) {
  wait(2000);                 // On attend par ce que les autres fonctions attendaient aussi ... Peut être inutile ...
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 999;         // Id qu'on va tester ... Je préfère commencer à 999, je pense pas qu'on va aller jusqu'à 99999 si ?
  snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux
    while (!SD.exists(filename)) {           // tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                           // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                // => Donc on break pour sortir du while
      idx --;                                 // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx); // on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                        // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))               // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      //    if(buttonPlay.risingEdge() || buttonRecord.risingEdge()) { // FIX
      if (buttonPlay.fallingEdge() || buttonRecord.risingEdge()) {
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    mode = Mode::Ready; print_mode();
    end_Beep();

    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);

    if (idx == 0)  // Si 0 alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
  }
  // All files have been played
  mode = Mode::Ready; print_mode();
}

Ci dessus un code qui devrait pouvoir lire les n derniers fichiers à ajouter dans le code et à appeler au bon endroit à la place de la fonction playAllRecordings();

disclaimer, je n'ai ni testé ni compilé donc si ça se trouve ça compile pas ...  on est jamais à l'abris d'une faute d'inattention ...mais si une coquille s'est glissé la logique est expliquée dans les commentaires ça devrait pouvoir se modifier. En français les commentaires que j'ai ajouté liés à la logique que j'ai ajouté, en anglais les commentaires des parties des fonctions playAll et playLast que j'ai copié pour faire ma fonction. 

N'hésite pas à me dire si ça marche comme prévu et si il y a une erreur ou que ça ne marche pas comme prévu à dire ce qui se passe pour qu'on puisse corriger. 
@+


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#5 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 07 mars 2023 - 01:37



void playLastRecordings(uint8_t n) {
  wait(2000);                 // On attend par ce que les autres fonctions attendaient aussi ... Peut être inutile ...
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 999;         // Id qu'on va tester ... Je préfère commencer à 999, je pense pas qu'on va aller jusqu'à 99999 si ?
  snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension
  for (uint8_t i = 0; i++; i < n ) {         // on va jouer n morceaux
    while (!SD.exists(filename)) {           // tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                           // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                // => Donc on break pour sortir du while
      idx --;                                 // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx); // on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                        // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))               // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();
    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      //    if(buttonPlay.risingEdge() || buttonRecord.risingEdge()) { // FIX
      if (buttonPlay.fallingEdge() || buttonRecord.risingEdge()) {
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    mode = Mode::Ready; print_mode();
    end_Beep();

    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);

    if (idx == 0)  // Si 0 alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
  }
  // All files have been played
  mode = Mode::Ready; print_mode();
}

Ci dessus un code qui devrait pouvoir lire les n derniers fichiers à ajouter dans le code et à appeler au bon endroit à la place de la fonction playAllRecordings();

disclaimer, je n'ai ni testé ni compilé donc si ça se trouve ça compile pas ...  on est jamais à l'abris d'une faute d'inattention ...mais si une coquille s'est glissé la logique est expliquée dans les commentaires ça devrait pouvoir se modifier. En français les commentaires que j'ai ajouté liés à la logique que j'ai ajouté, en anglais les commentaires des parties des fonctions playAll et playLast que j'ai copié pour faire ma fonction. 

N'hésite pas à me dire si ça marche comme prévu et si il y a une erreur ou que ça ne marche pas comme prévu à dire ce qui se passe pour qu'on puisse corriger. 
@+

 

Bonjour,

merci beaucoup pour la réactivité, je viens de coller le code, et j'ai supposé qu'il fallait modifier n mais ça ne fonctionne pas.
où faut-il le modifier exactement? par exemple pour lire les 5 derniers enregistrements
J'ai bien appelé plus haut ça je pense que c'est bon

Lorsque je ne change pas n j'ai ça en erreur:

 

Arduino : 1.8.19 (Windows 10), TD: 1.57, Carte : "Teensy 4.0, MTP Disk (Experimental), 150 MHz, Faster, French, Bigger blocks (256 samples)"





















C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino: In function 'void loop()':

C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino:180:36: error: expected primary-expression before 'n'

         playLastRecordings(uint8_t n);

                                    ^

C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino:204:38: error: expected primary-expression before 'n'

           playLastRecordings(uint8_t n);

                                      ^

C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino: In function 'void playLastRecordings(uint8_t)':

C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino:355:30: warning: for increment expression has no effect [-Wunused-value]

   for (uint8_t i = 0; i++; i < n ) {         // on va jouer n morceaux

                              ^

Erreur de compilation pour la carte Teensy 4.0



Ce rapport pourrait être plus détaillé avec
l'option "Afficher les résultats détaillés de la compilation"
activée dans Fichier -> Préférences.

 



 



#6 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 07 mars 2023 - 02:15

Quand tu appelles la fonction tu dois remplacer n par un nombre comme ça : 
 

      else if(buttonPlay.fallingEdge()) {
        //playAllRecordings();
        //playlastRecordings();
        playLastRecordings(5); // joue les 5 derniers messages ( ou moins de 5 si il y en a pas 5 )
      }

 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#7 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 07 mars 2023 - 02:38

Quand tu appelles la fonction tu dois remplacer n par un nombre comme ça : 
 

      else if(buttonPlay.fallingEdge()) {
        //playAllRecordings();
        //playlastRecordings();
        playLastRecordings(5); // joue les 5 derniers messages ( ou moins de 5 si il y en a pas 5 )
      }

J'avais déjà essayé, mais j'ai ce message qui apparaît, et l'enregistrement fonctionne quand même mais le bouton lecture ne fonctionne pas du tout:

C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino: In function 'void playLastRecordings(uint8_t)':
C:\Users\moi\Desktop\projet telephone 2\projet_audio-guestbook\projet_audio-guestbook.ino:355:30: warning: for increment expression has no effect [-Wunused-value]
   for (uint8_t i = 0; i++; i < n ) {         // on va jouer n morceaux
                              ^
Memory Usage on Teensy 4.0:
  FLASH: code:106744, data:13540, headers:8736   free for files:1902596
   RAM1: variables:18912, code:104152, padding:26920   free for local variables:374304
   RAM2: variables:50528  free for malloc/new:473760

 


 



#8 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 08 mars 2023 - 11:10

Il y avait une petite coquille dans ma fonction j'ai édité mon message plus haut et tu peux la reprendre. 

Si tu veux savoir l'erreur c'était ça :

for (uint8_t i = 0; i++; i < n ) => for (uint8_t i = 0; < n; i++ )


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#9 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 08 mars 2023 - 04:35

Merci mais il y a encore quelque chose qui ne va pas.
Je n'ai plus de message d'erreur dans arduino mais j'ai 2 erreurs sur le téléphone:
Losque j'appuie sur le bouton lecture puis je décroche le combiné ça ne fonctionne pas, mais que je raccroche la lecture se met en marche mais j'entend en boucle le dernier message uniquement. Il faut que je décroche le combiné pour que la lecture s'arrête. (en fait je suppose que le risingEdge et fallingEdge sont inversés, pourtant je ne les ai pas touché).
Alors j'ai testé d'appeler l'ancienne fonction PlayAllRecordings sans rien changer d'autre et je vois que le décrocher/raccrocher fonctionnent dans le bon sens avec cette fonction.

De plus j'ai fait plusieurs essais et je remarque que le n ne lit pas les n derniers messages mais plutôt le dernier message n-1 fois.

Alors j'ai deux questions:
Fallait-il bien copier tout le code que tu as fait dans la première réponse? je l'ai copié et ajouté au code que j'avais déjà.
Fallait-il bien ajouter le nombre d’enregistrements à lire dans la partie ci-dessous?

switch(mode){
    case Mode::Ready:
      // Falling edge occurs when the handset is lifted --> 611 telephone
      if (buttonRecord.fallingEdge()) {
        Serial.println("Handset lifted");
        mode = Mode::Prompting; print_mode();
      }
      else if(buttonPlay.fallingEdge()) {
        //playAllRecordings();
        playLastRecordings(6);
      }
      break;

    case Mode::Prompting:
      // Wait a second for users to put the handset to their ear
      wait(1000);
      // Play the greeting inviting them to record their message
      playWav1.play("greeting.wav");    
      // Wait until the  message has finished playing
//      while (playWav1.isPlaying()) {
      while (!playWav1.isStopped()) {
        // Check whether the handset is replaced
        buttonRecord.update();
        buttonPlay.update();
        // Handset is replaced
        if(buttonRecord.risingEdge()) {
          playWav1.stop();
          mode = Mode::Ready; print_mode();
          return;
        }
        if(buttonPlay.fallingEdge()) {
          playWav1.stop();
          //playAllRecordings();
         playLastRecordings(6);
          return;
        }

 





 



#10 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 09 mars 2023 - 02:49

Oui c'est bien comme ce que tu as fait qu'il fallait intégrer le code.
Par contre comme expliqué je n'ai pas pu tester le code ;) Il doit y avoir encore une petite coquille, mais je dois pouvoir trouver une correction à faire avec les remarques des problèmes rencontrés. 

Afin de nous aider à trouver le problème tu peux essayer cette fonction et refaire les essais en ayant l'usb de la teensy branchée à l'ordinateur afin d'afficher le texte sur le moniteur série. 
Du coup tu pourras poster ce que le moniteur série à affiché pendant ton test en expliquant ce que tu as fait au même moment... 

Genre si tu raccroches / décroche ou autre ... 


 

void playLastRecordings(uint8_t n) {
  wait(2000);                 // On attend par ce que les autres fonctions attendaient aussi ... Peut être inutile ...
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 999;         // Id qu'on va tester ... Je préfère commencer à 999, je pense pas qu'on va aller jusqu'à 99999 si ?
  snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension
  Serial.println("La boucle for commence");
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux
    Serial.print("boucle ");
    Serial.println(i);
    Serial.print("Idx = ");
    Serial.println(idx);
    while (!SD.exists(filename)) {           // tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                           // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                // => Donc on break pour sortir du while
      idx --;                                 // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx); // on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                        // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))               // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();

    while (!playWav1.isStopped()) { // this works for playWav
      bool onstop = false;
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      if(buttonPlay.risingEdge()) {
         Serial.println(" Boutton play rising");
      }
      if( buttonRecord.fallingEdge()) {
         Serial.println(" Boutton record falling");
      }
      if (buttonPlay.fallingEdge()) {
         onstop = true;
         Serial.println(" Boutton play falling");
      } 
      if( buttonRecord.risingEdge()) {
        onstop = true;
        Serial.println(" Boutton record rising");
      }
      if(onstop) {
        Serial.println(" on stop ");
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    Serial.println("Fin du son");
    mode = Mode::Ready; print_mode();
    end_Beep();
    Serial.println(" bip");
    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);
    Serial.println("fin du bip");
    if (idx == 0)  // Si 0 alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
    Serial.print("idx =");
    Serial.println(idx);
  }
  // All files have been played
  Serial.println("Fin de la boucle for");
  mode = Mode::Ready; print_mode();
}

Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#11 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 09 mars 2023 - 08:55

Alors la je viens de décrocher, j'ai entendu le "greeting", puis j'ai raccroché avant la fin. J'ai ensuite appuyé sur le bouton lecture, et le dernier enregistrement s'est mis à tourner en boucle comme indiqué dans ma réponse précédente.
Je remarque aussi que le délai entre l'appui sur le bouton et le début de la lecture est plus long que d'habitude. J'ai vu dans les commentaire que tu disais que c'etait peut-être inutile d'attendre, mais dans la pratique c'est parce que ça laisse le temps de mettre le combiné à l'oreille avant de commencer à lire les pistes. Bon maintenant c'est trop long, je ne sais pas pourquoi mais ça je pense pouvoir le corriger en enlevant le wait(2000)?

Edit: je viens de tester d'enlever le wait(2000) et le délai de lecture est toujours long, environ 5/6 secondes.
Le décrocher/raccrocher sont dans le bon sens cette fois :)

Voici ce que me donne le serial monitor
 

Handset lifted
Mode switched to:  Prompting
Mode switched to:  Ready
Button (pin 1) Release
La boucle for commence
boucle 0
Idx = 999
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =13
boucle 1
Idx = 13
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =12
boucle 2
Idx = 12
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =11
boucle 3
Idx = 11
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =10
boucle 4
Idx = 10
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =9
boucle 5
Idx = 9
 00014.wav
Mode switched to:  Playing
Fin du son
Mode switched to:  Ready
 bip
fin du bip
idx =8
Fin de la boucle for
Mode switched to:  Ready



#12 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 10 mars 2023 - 10:33

void playLastRecordings(uint8_t n) {
  wait(500);                 // On attend un peu histoire de laisser le temps à l'utilisateur de mettre le combiné à l'oreille
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 100;         // Id qu'on va tester ... Je préfère commencer à 100, je pense pas qu'on va aller jusqu'à 99999 si ? à changer si tu veux mettre plus de 100 messages mais ça va augmenter le délais d'attente
  Serial.println("La boucle for commence");
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux

    snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension

    Serial.print("boucle ");                   // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(i);                         // ligne à effacer du code final, uniquement utile pour le debug
    Serial.print("Idx = ");                    // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);                       // ligne à effacer du code final, uniquement utile pour le debug
    while (!SD.exists(filename)) {             // Tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                            // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                 // => Donc on break pour sortir du while
      idx --;                                  // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx);// on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                          // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))                // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found  // ligne à effacer du code final, uniquement utile pour le debug
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();

    while (!playWav1.isStopped()) { // this works for playWav
      bool onstop = false;
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      if(buttonPlay.risingEdge()) {
         Serial.println(" Boutton play rising");  // ligne à effacer du code final, uniquement utile pour le debug
      }
      if( buttonRecord.fallingEdge()) {
         Serial.println(" Boutton record falling"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if (buttonPlay.fallingEdge()) {
         onstop = true;
         Serial.println(" Boutton play falling"); // ligne à effacer du code final, uniquement utile pour le debug
      } 
      if( buttonRecord.risingEdge()) {
        onstop = true;
        Serial.println(" Boutton record rising"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if(onstop) {
        Serial.println(" on stop "); // ligne à effacer du code final, uniquement utile pour le debug
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    Serial.println("Fin du son"); // ligne à effacer du code final, uniquement utile pour le debug
    mode = Mode::Ready; print_mode();
    end_Beep();
    Serial.println(" bip");      // ligne à effacer du code final, uniquement utile pour le debug
    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);
    Serial.println("fin du bip"); // ligne à effacer du code final, uniquement utile pour le debug
    if (idx == 0)  // Si 0 alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
    Serial.print("idx =");  // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);    // ligne à effacer du code final, uniquement utile pour le debug
  }
  // All files have been played
  Serial.println("Fin de la boucle for");  // ligne à effacer du code final, uniquement utile pour le debug
  mode = Mode::Ready; print_mode();
}

Du coup grâce à ton retour j'ai trouvé la coquille ;) j'ai déplacé la ligne snprintf(filename, 11, " %05d.wav", idx); 

 

 

Et l'ai mise dans la boucle for. 
Maintenant ça devrait bien jouer les n dernier et pas n fois le dernier ;) 

Pour ce qui est du délais, il y a bien le wait qui a un impact mais aussi le chiffre à partir duquel tu commences ta vérification, afin de raccourcir le délais je t'ai modifié la chose pour commencer à 100 au lieu de 999 ...  Mais du coup ça veut dire que ça ne va marche correctement que si tu as 100 messages ou moins ... Et le temps d'attente et dépendant du nombre de messages que tu as ... 

Vu que j'ai mis un wait de 500,  ça attendra 500ms si tu as 100 messages, et ça attendra plus longtemps si tu en as que 5 car ça va passer du temps à tester tous les fichier de 100 à 5 jusqu'à trouver que le fichier existe.


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#13 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 10 mars 2023 - 12:03

void playLastRecordings(uint8_t n) {
  wait(500);                 // On attend un peu histoire de laisser le temps à l'utilisateur de mettre le combiné à l'oreille
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 100;         // Id qu'on va tester ... Je préfère commencer à 100, je pense pas qu'on va aller jusqu'à 99999 si ? à changer si tu veux mettre plus de 100 messages mais ça va augmenter le délais d'attente
  Serial.println("La boucle for commence");
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux

    snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension

    Serial.print("boucle ");                   // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(i);                         // ligne à effacer du code final, uniquement utile pour le debug
    Serial.print("Idx = ");                    // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);                       // ligne à effacer du code final, uniquement utile pour le debug
    while (!SD.exists(filename)) {             // Tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                            // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                 // => Donc on break pour sortir du while
      idx --;                                  // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx);// on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                          // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))                // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found  // ligne à effacer du code final, uniquement utile pour le debug
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();

    while (!playWav1.isStopped()) { // this works for playWav
      bool onstop = false;
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      if(buttonPlay.risingEdge()) {
         Serial.println(" Boutton play rising");  // ligne à effacer du code final, uniquement utile pour le debug
      }
      if( buttonRecord.fallingEdge()) {
         Serial.println(" Boutton record falling"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if (buttonPlay.fallingEdge()) {
         onstop = true;
         Serial.println(" Boutton play falling"); // ligne à effacer du code final, uniquement utile pour le debug
      } 
      if( buttonRecord.risingEdge()) {
        onstop = true;
        Serial.println(" Boutton record rising"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if(onstop) {
        Serial.println(" on stop "); // ligne à effacer du code final, uniquement utile pour le debug
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    Serial.println("Fin du son"); // ligne à effacer du code final, uniquement utile pour le debug
    mode = Mode::Ready; print_mode();
    end_Beep();
    Serial.println(" bip");      // ligne à effacer du code final, uniquement utile pour le debug
    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);
    Serial.println("fin du bip"); // ligne à effacer du code final, uniquement utile pour le debug
    if (idx == 0)  // Si 0 alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
    Serial.print("idx =");  // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);    // ligne à effacer du code final, uniquement utile pour le debug
  }
  // All files have been played
  Serial.println("Fin de la boucle for");  // ligne à effacer du code final, uniquement utile pour le debug
  mode = Mode::Ready; print_mode();
}

Du coup grâce à ton retour j'ai trouvé la coquille ;) j'ai déplacé la ligne snprintf(filename, 11, " %05d.wav", idx); 

 

 

Et l'ai mise dans la boucle for. 
Maintenant ça devrait bien jouer les n dernier et pas n fois le dernier ;) 

Pour ce qui est du délais, il y a bien le wait qui a un impact mais aussi le chiffre à partir duquel tu commences ta vérification, afin de raccourcir le délais je t'ai modifié la chose pour commencer à 100 au lieu de 999 ...  Mais du coup ça veut dire que ça ne va marche correctement que si tu as 100 messages ou moins ... Et le temps d'attente et dépendant du nombre de messages que tu as ... 

Vu que j'ai mis un wait de 500,  ça attendra 500ms si tu as 100 messages, et ça attendra plus longtemps si tu en as que 5 car ça va passer du temps à tester tous les fichier de 100 à 5 jusqu'à trouver que le fichier existe.

 

C'est super merci beaucoup ça fonctionne parfaitement.
J'avais déjà ajouté un wait plus haut à l'appel de la fonction et c'est suffisant avec les test que j'ai fait pour avoir le temps de prendre le combiné.
Aussi, j'ai changé le nombre de messages pour mettre 300. Le délai ne me parait pas très long (31 fichiers sur la carte SD). Plus il va y avoir de fichiers sur la carte et plus le délai sera court? ou l'inverse?

Dernière chose pour chipoter mais bien pratique, lorsque je met en lecture par exemple les 10 derniers messages, j'aimerai pouvoir arrêter la lecture au moment ou le combiné est replacé car actuellement ni le bouton ni le combiné n'arrêtent la lecture, il faut du coup attendre que tous les fichiers soient lus.

edit:
j'ai essayé avec mes déductions de rajouter ça mais çe ne stoppe que l'enregistrement en cours, et ça passe au suivant:

case Mode::Playing: 
     if (buttonRecord.fallingEdge()) {
          playWav1.stop();
          mode = Mode::Ready; print_mode();
      break;  
    }

 


 



#14 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 10 mars 2023 - 02:46

Ok pour tout arrêter c'est assez simple voilà le code modifié :)

 

void playLastRecordings(uint8_t n) {
  wait(500);                 // On attend un peu histoire de laisser le temps à l'utilisateur de mettre le combiné à l'oreille
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 100;         // Id qu'on va tester ... Je préfère commencer à 100, je pense pas qu'on va aller jusqu'à 99999 si ? à changer si tu veux mettre plus de 100 messages mais ça va augmenter le délais d'attente
  Serial.println("La boucle for commence");
  bool onstop = false;
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux

    snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension

    Serial.print("boucle ");                   // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(i);                         // ligne à effacer du code final, uniquement utile pour le debug
    Serial.print("Idx = ");                    // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);                       // ligne à effacer du code final, uniquement utile pour le debug
    while (!SD.exists(filename)) {             // Tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                            // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                 // => Donc on break pour sortir du while
      idx --;                                  // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx);// on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                          // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))                // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found  // ligne à effacer du code final, uniquement utile pour le debug
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();

    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      if(buttonPlay.risingEdge()) {
         Serial.println(" Boutton play rising");  // ligne à effacer du code final, uniquement utile pour le debug
      }
      if( buttonRecord.fallingEdge()) {
         Serial.println(" Boutton record falling"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if (buttonPlay.fallingEdge()) {
         onstop = true;
         Serial.println(" Boutton play falling"); // ligne à effacer du code final, uniquement utile pour le debug
      } 
      if( buttonRecord.risingEdge()) {
        onstop = true;
        Serial.println(" Boutton record rising"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if(onstop) {
        Serial.println(" on stop "); // ligne à effacer du code final, uniquement utile pour le debug
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    Serial.println("Fin du son"); // ligne à effacer du code final, uniquement utile pour le debug
    mode = Mode::Ready; print_mode();
    end_Beep();
    Serial.println(" bip");      // ligne à effacer du code final, uniquement utile pour le debug
    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);
    Serial.println("fin du bip"); // ligne à effacer du code final, uniquement utile pour le debug
    if (idx == 0 || onstop)  // Si 0 ou demande de stop alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
    Serial.print("idx =");  // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);    // ligne à effacer du code final, uniquement utile pour le debug
  }
  // All files have been played
  Serial.println("Fin de la boucle for");  // ligne à effacer du code final, uniquement utile pour le debug
  mode = Mode::Ready; print_mode();
}

Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#15 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 969 messages
  • Gender:Male
  • Location:Anglet

Posté 10 mars 2023 - 02:53

 Plus il va y avoir de fichiers sur la carte et plus le délai sera court? ou l'inverse?
 

 

Plus il va y avoir de fichier sur la carte plus le delais de " test d'existence de fichier " sera court. 

Le code test le 100 puis le 99 puis le 98 etc jusqu'à atteindre le 31 ... il y a un temps ( petit mais non nul ) pour chaque test avant d'atteindre un fichier qui existe. ça mettra forcément plus de temps de tester de 100 à 31 que de 100 à 98 si jamais tu as 98 fichiers ...


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#16 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 10 mars 2023 - 03:28

Plus il va y avoir de fichier sur la carte plus le delais de " test d'existence de fichier " sera court. 

Le code test le 100 puis le 99 puis le 98 etc jusqu'à atteindre le 31 ... il y a un temps ( petit mais non nul ) pour chaque test avant d'atteindre un fichier qui existe. ça mettra forcément plus de temps de tester de 100 à 31 que de 100 à 98 si jamais tu as 98 fichiers ...

C'est bien ce que j'avais compris mais je n'etais pas sur, merci. Et dans l'hypothèse où il y aurait plus de fichier comment ça se passe? Avec ton exemple si il teste à partir de 100, je suppose que les fichiers à partir de 100 ne seront jamais lu? Mais l'enregistrement continuera normalement, c'est ça?



#17 La Fabrik

La Fabrik

    Membre

  • Membres
  • 11 messages

Posté 10 mars 2023 - 03:31

 

Ok pour tout arrêter c'est assez simple voilà le code modifié :)

 

void playLastRecordings(uint8_t n) {
  wait(500);                 // On attend un peu histoire de laisser le temps à l'utilisateur de mettre le combiné à l'oreille
  File dir = SD.open("/");    // Recording files are saved in the root directory
  uint16_t idx = 100;         // Id qu'on va tester ... Je préfère commencer à 100, je pense pas qu'on va aller jusqu'à 99999 si ? à changer si tu veux mettre plus de 100 messages mais ça va augmenter le délais d'attente
  Serial.println("La boucle for commence");
  bool onstop = false;
  for (uint8_t i = 0; i < n; i++ ) {         // on va jouer n morceaux

    snprintf(filename, 11, " %05d.wav", idx);  //  Format the counter as a five-digit number with leading zeroes, followed by file extension

    Serial.print("boucle ");                   // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(i);                         // ligne à effacer du code final, uniquement utile pour le debug
    Serial.print("Idx = ");                    // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);                       // ligne à effacer du code final, uniquement utile pour le debug
    while (!SD.exists(filename)) {             // Tant que le fichier existe pas on décrémente l'ID
      if (idx == 0)                            // Si ID est à 0 on ne peut pas décrémenter plus ...
        break;                                 // => Donc on break pour sortir du while
      idx --;                                  // Sinon on décrémente id ( jusqu'à trouver un fichier ou que id = 0 )
      snprintf(filename, 11, " %05d.wav", idx);// on met à jour filename avec la nouveur valeurs d'id
    }
    if ( idx == 0 ) {                          // cas particulier ou id = 0 et on a break le while alors que le fichier existe pas
      if (!SD.exists(filename))                // on vérifie si le fichier existe
        break;                                 // Si il existe pas on break le for ( fin des fichiers )
    }

    // code copié de la fonction "play last "
    Serial.println(filename);   // Display the the file name we found  // ligne à effacer du code final, uniquement utile pour le debug
    playWav1.play(filename);    // Play the file
    mode = Mode::Playing; print_mode();

    while (!playWav1.isStopped()) { // this works for playWav
      buttonPlay.update();
      buttonRecord.update();
      // Button is pressed again
      if(buttonPlay.risingEdge()) {
         Serial.println(" Boutton play rising");  // ligne à effacer du code final, uniquement utile pour le debug
      }
      if( buttonRecord.fallingEdge()) {
         Serial.println(" Boutton record falling"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if (buttonPlay.fallingEdge()) {
         onstop = true;
         Serial.println(" Boutton play falling"); // ligne à effacer du code final, uniquement utile pour le debug
      } 
      if( buttonRecord.risingEdge()) {
        onstop = true;
        Serial.println(" Boutton record rising"); // ligne à effacer du code final, uniquement utile pour le debug
      }
      if(onstop) {
        Serial.println(" on stop "); // ligne à effacer du code final, uniquement utile pour le debug
        playWav1.stop();
        mode = Mode::Ready; print_mode();
      }
    }
    // file has been played
    Serial.println("Fin du son"); // ligne à effacer du code final, uniquement utile pour le debug
    mode = Mode::Ready; print_mode();
    end_Beep();
    Serial.println(" bip");      // ligne à effacer du code final, uniquement utile pour le debug
    // code copié de play all
    // Play a short beep before each message
    waveform1.amplitude(beep_volume);
    wait(750);
    waveform1.amplitude(0);
    Serial.println("fin du bip"); // ligne à effacer du code final, uniquement utile pour le debug
    if (idx == 0 || onstop)  // Si 0 ou demande de stop alors il y a plus de son à jouer c'est fini on break le for
      break;
    idx --;        // sinon décrémenter pour jouer le fichier précédent grâce au for
    Serial.print("idx =");  // ligne à effacer du code final, uniquement utile pour le debug
    Serial.println(idx);    // ligne à effacer du code final, uniquement utile pour le debug
  }
  // All files have been played
  Serial.println("Fin de la boucle for");  // ligne à effacer du code final, uniquement utile pour le debug
  mode = Mode::Ready; print_mode();
}

C'est génial ça marche, un grand merci pour ton aide et pour tes annotations qui me permettent de comprendre un peu comment ça marche. J'ai passé une deuxième commande hier, je vais pouvoir garder celui là et m'exercer sur un nouveau, j'aimerai par exemple remplacer le bouton lecture par le chiffre 9 ou 0 du cadran et faire plein d'autre essais.
Encore merci c'est top !





Répondre à ce sujet



  


0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users