Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 17 of 17

Thread: Cant compile code based on audioshield example

  1. #1

    Cant compile code based on audioshield example

    I am using a modified version of Paul's example code for recording and playing back audio using teensy 4.0 and audio shield. Everything looks good except I am getting errors on all of the subroutine calls based on what the button does:

    if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
    }

    Error: "message": "'stopPlaying' was not declared in this scope"

    I am using PlatformIO in vsCode if that makes a difference.

    Full code:

    Code:
     #include <Arduino.h>
    #include <korg_syro_volcasample.h>
    // Three pushbuttons need to be connected:
    //   Record Button: pin 0 to GND
    //   Stop Button:   pin 1 to GND
    //   Play Button:   pin 2 to GND
    //   Syro Button:   pin 3 to GND
    // This example code is in the public domain.
    
    #include <SPI.h>
    #include <SD.h>
    #include <SD_t3.h>
    #include <SerialFlash.h>
    
    #include <Audio.h>
    #include <Bounce.h>
    #include <Wire.h>
    
    //write wav
    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;
    
    // which input on the audio shield will be used?
    const int myInput = AUDIO_INPUT_LINEIN;
    //const int myInput = AUDIO_INPUT_MIC;
    
    AudioPlaySdWav           audioSD;
    AudioInputI2S            audioInput;
    AudioOutputI2S           audioOutput;
    AudioRecordQueue         queue1;
    
    //recod from mic
    AudioConnection          patchCord1(audioInput, 0, queue1, 0);
    AudioConnection          patchCord2(audioSD, 0, audioOutput, 0);
    AudioConnection          patchCord3(audioSD, 0, audioOutput, 1);
    
    AudioControlSGTL5000     audioShield;
    
    // Use these with the Teensy Audio Shield
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  7
    #define SDCARD_SCK_PIN   14
     
    // Remember which mode we're doing
    int mode = 0;  // 0=stopped, 1=recording, 2=playing
    elapsedMillis  msecs;
    
    // Bounce objects to easily and reliably read the buttons
    Bounce buttonRecord = Bounce(0, 8);
    Bounce buttonStop =   Bounce(1, 8);  // 8 = 8 ms debounce time
    Bounce buttonPlay =   Bounce(2, 8);
    Bounce buttonSyro =   Bounce(3, 8);
    
    //////Korg Required Variables/////////////
    uint8_t *pData; // pointer which specifies the data to be converted.
    uint32_t Number; // the sample (0-99) or sequence pattern (0-9) number.
    uint32_t Size; // size of data to be converted (in bytes).
                  // set it to sizeof(VolcaSample_Pattern_Data) when converting sequence data.
    uint32_t Quality; // The conversion bit depth. It can be set to 8-16. **By default this is set to 16.
    Endian SampleEndian; //set to LittleEndian or BigEndian to suite your sample data.
    int NumOfData; //The number of files we are sending to be converted by the syro converter process. When not specified, this is set to 1 by default.
    uint32_t Flags; //This is always set to 0
    uint32_t *pNumOfSyroFrame; // the pointer of the value which stores the size of the SyroData after conversion. Units in frames (an LR pair is one unit)
    
    /////References for Syro Stuff/////
    SyroDataType DataType;
    //specifies any of the following data type to be converted.  
    //DataType_Sample_Compress        //: convert single audio sample  
    //DataType_Sample_Erase           //: delete single sample slot on volca sample  
    //DataType_Sample_AllCompress     //: convert all sample data  
    //DataType_Pattern       
    
    
    // The file where data is recorded
    File frec; 
    
    void setup() {
    ///Korg Syro variables setup
    // Quality = 16;
    // Size = 512;
    // SampleEndian = BigEndian;
    // DataType = DataType_Sample_Compress;
    // NumOfData = 1; //for testing, this is being set to 1
    // Number = 1;
    
      // Configure the pushbutton pins
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, 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
      audioShield.enable();
      audioShield.inputSelect(myInput);
      //audioShield.micGain(40);  //0-63
      audioShield.volume(0.5);  //0-1
    
      // 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);
        }
      }
    }
    
    void loop() {
      // First, read the buttons
      buttonRecord.update();
      buttonStop.update();
      buttonPlay.update();
      buttonSyro.update();
    
      // Respond to button presses
      if (buttonRecord.fallingEdge()) {
        Serial.println("Record Button Press");
        if (mode == 2) stopPlaying();
        if (mode == 0) startRecording();
      }
      if (buttonStop.fallingEdge()) {
        Serial.println("Stop Button Press");
        if (mode == 1) stopRecording();
        if (mode == 2) stopPlaying();
      }
      if (buttonPlay.fallingEdge()) {
        Serial.println("Play Button Press");
        if (mode == 1) stopRecording();
        if (mode == 0) startPlaying();
      }
      if (buttonSyro.fallingEdge()) {
        Serial.println("Syro Button Press");
        if (mode == 1) stopRecording();
        if (mode == 0) SyroStatus SyroVolcaSample_Start(
                       SyroHandle *pHandle, 
                       SyroData *pData, 
                       int NumOfData,
                       uint32_t Flags,
                       uint32_t *pNumOfSyroFrame
                                                 );
      }
      // If we're playing or recording, carry on...
      if (mode == 1) {
        continueRecording();
      }
      if (mode == 2) {
        continuePlaying();
      }
    
      // when using a microphone, continuously adjust gain
     //  if (myInput == AUDIO_INPUT_MIC) adjustMicLevel();
    }
    
    void startRecording() {
      Serial.println("startRecording");
      if (SD.exists("RECORD.WAV")) {
        SD.remove("RECORD.WAV");
      }
      frec = SD.open("RECORD.WAV", FILE_WRITE);
      if (frec) {
        queue1.begin();
        mode = 1;
        recByteSaved = 0L;
      }
    }
    
    void continueRecording() {
      
      if (queue1.available() >= 2) {
        byte buffer[512];
        memcpy(buffer, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        memcpy(buffer + 256, queue1.readBuffer(), 256);
        queue1.freeBuffer();
        // write all 512 bytes to the SD card
        frec.write(buffer, 512);
        recByteSaved += 512;
    //    elapsedMicros usec = 0;
    //    Serial.print("SD write, us=");
    //    Serial.println(usec);
      }
    }
    
    void stopRecording() {
      Serial.println("stopRecording");
      queue1.end();
      if (mode == 1) {
        while (queue1.available() > 0) {
          frec.write((byte*)queue1.readBuffer(), 256);
          queue1.freeBuffer();
          recByteSaved += 256;
        }
        writeOutHeader();
        frec.close();
      }
      mode = 0;
    }
    
    void startPlaying() {
      Serial.println("startPlaying");
      audioSD.play("RECORD.WAV");
      mode = 2;
    
    }
    
    void stopPlaying() {
      Serial.println("stopPlaying");
      if (mode == 2) audioSD.stop();
      mode = 0;
    }
    
    
    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;
      ChunkSize = Subchunk2Size + 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); 
    }
    Last edited by massahwahl; 01-31-2020 at 02:24 PM.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,497
    Quote Originally Posted by massahwahl View Post
    I am using PlatformIO in vsCode if that makes a difference.
    Yes, it probably does make a difference. Can you give it a try in Arduino, just to confirm whether the problem is the code itself or a difference between Arduino & PlatformIO?

  3. #3
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    I don't get that error message. What I get is that continuePlaying is undefined. In the original example code, continuePlaying is defined between startPlaying and stopPlaying but in your code it isn't there. I suspect that what happened was that you didn't need that function and removed it from the sketch but didn't remove the code that called it. The code compiles when that call is commented.

    +edit Just seen Paul's reply. Looks like there is a difference between PlatformIO and Arduino IDE (which I used)
    Pete

  4. #4
    Quote Originally Posted by PaulStoffregen View Post
    Yes, it probably does make a difference. Can you give it a try in Arduino, just to confirm whether the problem is the code itself or a difference between Arduino & PlatformIO?
    Thank you for the reply, I tried running it in the Arduino IDE and got this error:

    arm-none-eabi-g++: error: CreateProcess: No such file or directory

    I am in a wee bit over my head so the problem is very likely that I am going to need to write a wrapper for the header files I am trying to use for the korg syro program.
    Last edited by massahwahl; 01-31-2020 at 03:21 PM.

  5. #5
    Quote Originally Posted by el_supremo View Post
    I don't get that error message. What I get is that continuePlaying is undefined. In the original example code, continuePlaying is defined between startPlaying and stopPlaying but in your code it isn't there. I suspect that what happened was that you didn't need that function and removed it from the sketch but didn't remove the code that called it. The code compiles when that call is commented..

    I actually caught that and edited the original post. The new code is in the original post and it does compile (almost) correctly in the Arduino IDE but not in PlatformIO. Its weird because I have never had issues with PIO before.

  6. #6
    Quote Originally Posted by PaulStoffregen View Post
    Yes, it probably does make a difference. Can you give it a try in Arduino, just to confirm whether the problem is the code itself or a difference between Arduino & PlatformIO?
    Paul am I naive/wrong in thinking that there is a clean way to use the Korg Syro library from within my sketch without a boatload of converting? I am not opposed to figuring out how to do it but before I go down that road I dont want to overlook anything obvious.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,497
    Quote Originally Posted by massahwahl View Post
    a clean way to use the Korg Syro library from within my sketch without a boatload of converting?
    Since that code does not appear to be designed to run on Teensy or any similar Arduino compatible board, I'm going to go with "no", though I suppose it does depend somewhat on the meaning of "clean" and "boatload".

    Looks like any hope of using that would involve quite a bit of work to adapt it to compile and run properly.

  8. #8
    Quote Originally Posted by PaulStoffregen View Post
    Since that code does not appear to be designed to run on Teensy or any similar Arduino compatible board, I'm going to go with "no", though I suppose it does depend somewhat on the meaning of "clean" and "boatload".

    Looks like any hope of using that would involve quite a bit of work to adapt it to compile and run properly.
    I was afraid of that... I set a goal to figure it out so hell or high water I suppose Iíll come up with a way to do it! I did figure out that my issue ended up being related to recently moving my Arduino folder to my NAS and not properly repointing Pio and AIDE to the right spot. The code will compile now with the headers but getting the functions to work the right way is going to be the battle.

  9. #9
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    I've had a brief look at the code and one of the things you'll have to be mindful of is that it was written for processors which have gigabytes of ram. In such an environment, what often happens is that the code is written such that it never expects to run out of memory.
    The Korg_syro code uses malloc and doesn't appear to be really careful about handling the case where malloc can return zero.
    For example, in korg_syro_comp.c, the function SyroComp_Comp uses malloc to allocate a map_buffer and returns zero if the malloc fails. SyroComp_Comp is only called in one place, in korg_syro_volcasample.c, but the return value isn't tested for zero.
    Similarly, SyroComp_GetCompSize returns zero if malloc fails but it is called in three places, none of which test for a return of zero.
    This sort of thing can cause mysterious crashes.
    If you're lucky, this is the only major problem and the rest of the conversion will be painless.
    Good luck.

    Pete

  10. #10
    Quote Originally Posted by el_supremo View Post
    I've had a brief look at the code and one of the things you'll have to be mindful of is that it was written for processors which have gigabytes of ram. In such an environment, what often happens is that the code is written such that it never expects to run out of memory.
    The Korg_syro code uses malloc and doesn't appear to be really careful about handling the case where malloc can return zero.
    For example, in korg_syro_comp.c, the function SyroComp_Comp uses malloc to allocate a map_buffer and returns zero if the malloc fails. SyroComp_Comp is only called in one place, in korg_syro_volcasample.c, but the return value isn't tested for zero.
    Similarly, SyroComp_GetCompSize returns zero if malloc fails but it is called in three places, none of which test for a return of zero.
    This sort of thing can cause mysterious crashes.
    If you're lucky, this is the only major problem and the rest of the conversion will be painless.
    Good luck.

    Pete
    Thank you! I don't know very much C programming but I have been meaning to learn so it's probably a good time to jump in to it. I appreciate you taking the time to offer some ideas of where to start! The Syros stuff can do more than I need, I am really only interested in the audio conversion and Sending/deleting saved samples and not any of the pattern stuff so hopefully that will make it a little simpler too.

  11. #11
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    I've had another look at the code and compiled the example code on my PC. It runs without any problem. I then added some debugging statements to print out the size of memory requested in each call to malloc. This is the output:
    Code:
    malloc:    2048 map_buffer 1
    malloc:     480 handle_size
    malloc:    2048 map_buffer 1
    malloc:   13568 comp_buf
    malloc:    2048 map_buffer 2
    malloc: 1321004 size_dest
    As you can see, a Teensy 4 would have no problem handling the first 5 allocations but the last one isn't going to work. What that does is allocate enough space for the entire output file - a 16-bit 44.1kHz stereo WAV.
    I don't know if I'll dig any deeper, but what you'll have to figure out is how to write that file in smaller pieces that the T4 can accommodate.

    Pete

  12. #12
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    It turned out to be easy to change the code so that it wrote the data in smaller pieces (256 byte blocks).
    Having done that it was also easy to change it so that it writes the data as audio to the audio board, which I think might be more useful.
    The attached zip should be unzipped into your teensy libraries directory. It contains two sketches in the "example" subdirectory.
    korg_syro_example_1
    This reads the example WAV file from the distribution and converts it into a (much larger) WAV file containing the audio which would be sent to the volca.
    korg_syro_example_2
    This also converts the example WAV file but it sends the audio out the headphones and line output on a Teensy audio board.

    I've tested these on a Teensy 4 but they should work on Teensy 3.* (with audio board for the second example).

    If you can try these out, I'd like to know whether the second example allows you to upload that sample to a Volca.

    Pete
    volcasample_teensy.zip

  13. #13
    Quote Originally Posted by el_supremo View Post
    It turned out to be easy to change the code so that it wrote the data in smaller pieces (256 byte blocks).
    Having done that it was also easy to change it so that it writes the data as audio to the audio board, which I think might be more useful.
    The attached zip should be unzipped into your teensy libraries directory. It contains two sketches in the "example" subdirectory.
    korg_syro_example_1
    This reads the example WAV file from the distribution and converts it into a (much larger) WAV file containing the audio which would be sent to the volca.
    korg_syro_example_2
    This also converts the example WAV file but it sends the audio out the headphones and line output on a Teensy audio board.

    I've tested these on a Teensy 4 but they should work on Teensy 3.* (with audio board for the second example).

    If you can try these out, I'd like to know whether the second example allows you to upload that sample to a Volca.

    Pete
    volcasample_teensy.zip
    I was not expecting anyone to take the time to dig this far into this, thank you! Sincerely! I was getting ready to jump back in tomorrow morning after a long work week last week and this was a very exciting surprise. I will let you know once I get it fired up in the morning!

  14. #14
    Quote Originally Posted by el_supremo View Post
    It turned out to be easy to change the code so that it wrote the data in smaller pieces (256 byte blocks).
    Having done that it was also easy to change it so that it writes the data as audio to the audio board, which I think might be more useful.
    The attached zip should be unzipped into your teensy libraries directory. It contains two sketches in the "example" subdirectory.
    korg_syro_example_1
    This reads the example WAV file from the distribution and converts it into a (much larger) WAV file containing the audio which would be sent to the volca.
    korg_syro_example_2
    This also converts the example WAV file but it sends the audio out the headphones and line output on a Teensy audio board.

    I've tested these on a Teensy 4 but they should work on Teensy 3.* (with audio board for the second example).

    If you can try these out, I'd like to know whether the second example allows you to upload that sample to a Volca.

    Pete
    volcasample_teensy.zip
    Tried two different SD cards and redownloaded the Korg library just to make sure I had not ever messed with that sample file. I have a couple T4 and music shields, I am going to solder one up and try it there. It could just be an issue with the 3.6

  15. #15
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    I forgot to mention that on your SD card, the sample input WAV file must be named 02Kick3.wav. The original name in the distribution, "02 Kick 3.wav", is too long to fit the 8.3 format required for the SD card on the Teensy.

    Pete

  16. #16
    Quote Originally Posted by el_supremo View Post
    I forgot to mention that on your SD card, the sample input WAV file must be named 02Kick3.wav. The original name in the distribution, "02 Kick 3.wav", is too long to fit the 8.3 format required for the SD card on the Teensy.

    Pete
    Aha! That took care of it for the T4. I am getting the signal to the VS now but its throwing an error when it tries to read the stream. They are notoriously finicky about the volume level and any other noise interference so I am messing around with the output volume from the music shield to see if I can zero in on where it isnt loud enough to be recognized as opposed to being to loud. Thank you again! This will give me a gigantic leg up learning how to deploy this when it comes time to adding the input into the equation.

  17. #17
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,252
    Are you using the headphone output and do you have the volume control potentiometer on the audio board?
    If so, you could try changing this:
    Code:
      sgtl5000_1.volume(0.4);
    to this:
    Code:
      int n = analogRead(15);
      sgtl5000_1.volume(n / 1023.);
    Serial.printf("volume = %4.2f\n",n/1023.);
    Set the pot to a low volume to start with and increase it a bit each time it fails to decode. The sketch prints out the volume being used, so if it works you'll know what to use as a "hard-coded" value.

    Pete

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •