Recorder_WAV -- Multiple Recordings



  • Good morning. I've been playing around with my SPRESENSE board and have the RECORDER_WAV example up and running perfectly. Now I'm trying to edit the code to be able to perform multiple recordings...

    Ex) Record a 10 second wav file called Audio_000.wav and save to SD Card. Then record another 10 second wav file called Audio_001.wav and save to SD Card. So on and so on.

    Since the Camera example does something similar with its JPG files, I attempted using the same sort of syntax with my new RECORDER_WAV file, but am running into a sleuth of issues...

    My attempt is pasted below, along with the Serial monitor output. Basically I attempted to use an IF statement to record 10 WAV files. I'm thinking I might be approaching this issue incorrectly. Any help or guidance would be greatly appreciated!

    #include <SDHCI.h>
    #include <Audio.h>
    #include <stdio.h>
    
    #include <arch/board/board.h>
    
    SDClass theSD;
    AudioClass *theAudio;
    
    File myFile;
    int file_count = 0;
    
    bool ErrEnd = false;
    
    static void audio_attention_cb(const ErrorAttentionParam *atprm)
    {
      puts("Attention!");
      
      if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
        {
          ErrEnd = true;
       }
    }
    
    static const uint32_t recoding_sampling_rate = 48000;
    static const uint8_t  recoding_cannel_number = 4;
    static const uint8_t  recoding_bit_length = 16;
    static const uint32_t recoding_time = 10;
    static const int32_t recoding_byte_per_second = recoding_sampling_rate *
                                                    recoding_cannel_number *
                                                    recoding_bit_length / 8;
    static const int32_t recoding_size = recoding_byte_per_second * recoding_time;
    
    void setup()
    {
      theAudio = AudioClass::getInstance();
    
      theAudio->begin(audio_attention_cb);
    
      puts("initialization Audio Library");
    
      theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC, 210);
    
      theAudio->initRecorder(AS_CODECTYPE_WAV,
                             "/mnt/sd0/BIN",
                             recoding_sampling_rate,
                             recoding_bit_length,
                             recoding_cannel_number);
      puts("Init Recorder!");
    }
    
    void loop() 
    {
      if (file_count < 10)
      {
        char filename[16] = {0};
        sprintf(filename, "Test%03d.wav", file_count);
        myFile = theSD.open(filename, FILE_WRITE);
        
      if (!myFile)
        {
          printf("File open error\n");
          exit(1);
        }
    
      theAudio->writeWavHeader(myFile);
      puts("Write Header!");
    
      theAudio->startRecorder();
      puts("Recording Start!");
    
      file_count++;
    
      err_t err;
      
      if (theAudio->getRecordingSize() > recoding_size)
        {
          theAudio->stopRecorder();
          sleep(1);
          err = theAudio->readFrames(myFile);
    
          goto exitRecording;
        }
    
      err = theAudio->readFrames(myFile);
    
      if (err != AUDIOLIB_ECODE_OK)
        {
          printf("File End! =%d\n",err);
          theAudio->stopRecorder();
          goto exitRecording;
        }
    
      if (ErrEnd)
        {
          printf("Error End\n");
          theAudio->stopRecorder();
          goto exitRecording;
        }
      }
      
      return;
    
    exitRecording:
    
      theAudio->closeOutputFile(myFile);
      myFile.close();
      
      theAudio->setReadyMode();
      theAudio->end();
      
      puts("End Recording");
      exit(1);
    }
    
    initialization Audio Library
    Init Recorder!
    Write Header!
    Recording Start!
    Write Header!
    ERROR: Command (0x32) fails. Result code(0xf1) Module id(0x2) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Write Header!
    ERROR: Command (0x32) fails. Result code(0xf1) Module id(0x2) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Write Header!
    ERROR: Command (0x32)up_assert: Assertion failed at file:manager/audio_manager.cpp line: 3274 task: AMNG
    up_dumpstate: sp:     0d056684
    up_dumpstate: IRQ stack:
    up_dumpstate:   base: 0d046a00
    up_dumpstate:   size: 00000800
    up_dumpstate:   used: 000000f0
    up_dumpstate: User stack:
    up_dumpstate:   base: 0d056778
    up_dumpstate:   size: 000007ec
    up_dumpstate:   used: 000002c0
    up_stackdump: 0d056680: 00000000 0d045e14 00000000 0d010a5b 0d056698 000fd340 08f10000 00000001
    up_stackdump: 0d0566a0: 040067b0 00000000 0000e503 0d03de58 0d0567b0 0d0117ff 0d01ff08 0d0567b0
    up_stackdump: 0d0566c0: 0d0567d8 0d010cc5 00000000 00000000 0d0567b0 00000032 0d0566fc 0d010de1
    up_stackdump: 0d0566e0: 0d0567b0 0d0566fc 0d0566fc 00000000 000fd8bc 0d011dbf 00000000 00040032
    up_stackdump: 0d056700: 00000001 00000000 000fd040 00000127 000fd040 0d00e213 000fd040 ffffffff
    up_stackdump: 0d056720: 0d05674c 0d0567b0 00000000 00000001 0d0567b0 00000000 00000001 0d045e14
    up_stackdump: 0d056740: 00000008 0d011f17 000fd040 000fd8bc 0d000245 0d011f8f 00000000 0d011fbf
    up_stackdump: 0d056760: 0d000245 00000000 00000000 0d001b4f 00000000 00000000 deadbeef 0d056784
    up_taskdump: Idle Task: PID=0 Stack Used=0 of 0
    up_taskdump: hpwork: PID=1 Stack Used=584 of 2028
    up_taskdump: lpwork: PID=2 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=3 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=4 Stack Used=352 of 2028
    up_taskdump: init: PID=5 Stack Used=1224 of 8172
    up_taskdump: cxd56_pm_task: PID=6 Stack Used=320 of 996
    up_taskdump: <pthread>: PID=7 Stack Used=320 of 1020
    up_taskdump: AMNG: PID=8 Stack Used=760 of 2028
    up_taskdump: PLY_OBJ: PID=9 Stack Used=320 of 3052
    up_taskdump: SUB_PLY_OBJ: PID=10 Stack Used=320 of 3044
    up_taskdump: OMIX_OBJ: PID=11 Stack Used=328 of 3044
    up_taskdump: RENDER_CMP_DEV0: PID=12 Stack Used=312 of 2020
    up_taskdump: RENDER_CMP_DEV1: PID=13 Stack Used=312 of 2020
    up_taskdump: FED_OBJ: PID=14 Stack Used=552 of 2028
    up_taskdump: REC_OBJ: PID=15 Stack Used=372 of 2028
    up_taskdump: CAPTURE_CMP_DEV0: PID=16 Stack Used=440 of 2012
     fails. Reup_assert: Assertion failed at file:objects/front_end/front_end_obj.cpp line: 119 task: FED_OBJ
    up_dumpstate: sp:     0d05ce54
    up_dumpstate: IRQ stack:
    up_dumpstate:   bassult codeup_assert: Assertion failed at file:objects/front_end/front_end_obj.cpp line: 89 task: CAPTURE_CMP_DEV0
    up_dumpstate: sp:     0d05f0f4
    up_dumpstate: IRQ stack:
    up_dumpstate:   base: 0d046a00
    up_dumpstate:   size: 00000800
    up_dumpstate:   used: 000000f0
    up_dumpstate: User stack:
    up_dumpstate:   base: 0d05f248
    up_dumpstate:   size: 000007dc
    up_dumpstate:   used: 00000320
    up_stackdump: 0d05f0e0: 0d05f104 0d00cfcf 00000000 000fd680 0d05f13c 0d05f200 00000000 0d0161b9
    up_stackdump: 0d05f100: 0d05f13c 000fd680 00006b00 00008000 0d05e230 0d05e240 0d01612f 0d00e851
    up_stackdump: 0d05f120: 00000306 0d00d493 0d05f100 00000000 00000300 00000000 0d039900 00000300
    up_stackdump: 0d05f140: 00000000 00000300 01000000 00000000 0d0872a0 0d087750 0d05e230 0d00fc79
    up_stackdump: 0d05f160: 6c6c6f72 612f7265 6f696475 61000000 0d0df010 00700300 00000000 0d080000
    up_stackdump: 0d05f180: 0d05e230 0d0872a0 0d05e230 0d05e230 0d05f200 0d00fd01 0d03995b 00000306
    up_stackdump: 0d05f1a0: 0d05e230 0d00f507 00000000 0d01018b 00000000 0d00ea59 00000000 00000000
    up_stackdump: 0d05f1c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    up_stackdump: 0d05f1e0: 00000000 0d01a9ab 0d05e230 000fe608 0d05e230 00000006 00000000 0d00e6a7
    up_stackdump: 0d05f200: 00000000 00000000 00000000 00000000 00000000 0d05e230 00000000 00000000
    up_stackdump: 0d05f220: 00000000 0d00f15f 000fd380 000fe608 00000101 0d00f1b1 0d00f18f 0d001b4f
    up_stackdump: 0d05f240: 00000000 00000000 deadbeef 0d05f254 00000000 54504143 5f455255 5f504d43
    up_taskdump: Idle Task: PID=0 Stack Used=0 of 0
    up_taskdump: hpwork: PID=1 Stack Used=584 of 2028
    up_taskdump: lpwork: PID=2 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=3 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=4 Stack Used=352 of 2028
    up_taskdump: init: PID=5 Stack Used=1224 of 8172
    up_taskdump: cxd56_pm_task: PID=6 Stack Used=320 of 996
    up_taskdump: <pthread>: PID=7 Stack Used=320 of 1020
    up_taskdump: AMNG: PID=8 Stack Used=760 of 2028
    up_taskdump: PLY_OBJ: PID=9 Stack Used=320 of 3052
    up_taskdump: SUB_PLY_OBJ: PID=10 Stack Used=320 of 3044
    up_taskdump: OMIX_OBJ: PID=11 Stack Used=328 of 3044
    up_taskdump: RENDER_CMP_DEV0: PID=12 Stack Used=312 of 2020
    up_taskdump: RENDER_CMP_DEV1: PID=13 Stack Used=312 of 2020
    up_taskdump: FED_OBJ: PID=14 Stack Used=760 of 2028
    up_taskdump: REC_OBJ: PID=15 Stack Used=372 of 2028
    up_taskdump: CAPTURE_CMP_DEV0: PID=16 Stack Used=856 of 2012
    e: 0d046a00
    up_dumpstate:   size: 00000800
    up_dumpstate:   used: 000000f0
    up_dumpstate: User stack:
    up_dumpstate:   base: 0d05cf98
    up_dumpstate:   size: 000007ec
    up_dumpstate:   used: 000002f8
    up_stackdump: 0d05ce40: 0d05ce64 0d00cfcf 00000000 00000000 000000fc 00000001 00000000 0d0162d1
    up_stackdump: 0d05ce60: 00000015 000fd680 00006b02 00008000 0d05ce90 0d08b7b0 00000001 00001800
    up_stackdump: 0d05ce80: 0d05cfd0 0d02da0d 0000000e 000ffc01 00000000 00000000 0004000d 00000300
    up_stackdump: 0d05cea0: 00001800 0d000100 00000001 00000000 0d05cfd0 0d015dc3 000ff054 0d00c81b
    up_stackdump: 0d05cec0: 0000000e 00000000 00000000 0004000d 00000300 00001800 00000100 00000000
    up_stackdump: 0d05cee0: 0d05cfd0 00000000 00000000 0d01610d 0004000d 00000000 00000300 00000000
    up_stackdump: 0d05cf00: 00000000 00000000 0004000d 00000300 00000001 0d01a900 000fd680 000fd680
    up_stackdump: 0d05cf20: 00000000 0d016f0f 0d05cfd0 000fd680 0d05cfd0 00000000 00000002 0d045e88
    up_stackdump: 0d05cf40: 00000001 0000001a 00000000 0d016ffb 00000000 00000000 00000000 001b011a
    up_stackdump: 0d05cf60: 0010000d 0000000d 00000000 00000010 00000000 00000000 00000000 00000000
    up_stackdump: 0d05cf80: 00000000 0d017049 00000101 0d001b4f 00000000 00000000 deadbeef 0d05cfa4
    up_taskdump: Idle Task: PID=0 Stack Used=0 of 0
    up_taskdump: hpwork: PID=1 Stack Used=584 of 2028
    up_taskdump: lpwork: PID=2 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=3 Stack Used=352 of 2028
    up_taskdump: lpwork: PID=4 Stack Used=352 of 2028
    up_taskdump: init: PID=5 Stack Used=1224 of 8172
    up_taskdump: cxd56_pm_task: PID=6 Stack Used=320 of 996
    up_taskdump: <pthread>: PID=7 Stack Used=320 of 1020
    up_taskdump: AMNG: PID=8 Stack Used=760 of 2028
    up_taskdump: PLY_OBJ: PID=9 Stack Used=320 of 3052
    up_taskdump: SUB_PLY_OBJ: PID=10 Stack Used=320 of 3044
    up_taskdump: OMIX_OBJ: PID=11 Stack Used=328 of 3044
    up_taskdump: RENDER_CMP_DEV0: PID=12 Stack Used=312 of 2020
    up_taskdump: RENDER_CMP_DEV1: PID=13 Stack Used=312 of 2020
    up_taskdump: FED_OBJ: PID=14 Stack Used=840 of 2028
    up_taskdump: REC_OBJ: PID=15 Stack Used=372 of 2028
    (0xf1) Module id(0x4) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Write Header!
    ERROR: Command (0x32) fails. Result code(0xf1) Module id(0x2) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Attention: module[1][0] attention id[2]/code[3] (dma_controller/audio_dma_drv.cpp L898)
    
    Attention: module[1][0] attention id[2]/code[7] (dma_controller/audio_dma_drv.cpp L774)
    
    Write Header!
    ERROR: Command (0x32) fails. Result code(0xf1) Module id(0x4) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Write Header!
    ERROR: Command (0x32) fails. Result code(0xf1) Module id(0x2) Error code(0x1) Error subcode(0x0)
    Recording Start!
    Write Header!
    

  • DeveloperWorld

    @user1388

    Just took a quick look at your code:

    Isn't it so that if this line err = theAudio->readFrames(myFile); is ok you will exit and enter the loop() function again and start the recorder again without ever have stopped it first.

    
    
    void loop() 
    {
      if (file_count < 10)
      {
        char filename[16] = {0};
        sprintf(filename, "Test%03d.wav", file_count);
        myFile = theSD.open(filename, FILE_WRITE);
        
      if (!myFile)
        {
          printf("File open error\n");
          exit(1);
        }
    
      theAudio->writeWavHeader(myFile);
      puts("Write Header!");
    
      theAudio->startRecorder();
      puts("Recording Start!");
    
      file_count++;
    
      err_t err;
      
      if (theAudio->getRecordingSize() > recoding_size)
        {
          theAudio->stopRecorder();
          sleep(1);
          err = theAudio->readFrames(myFile);
    
          goto exitRecording;
        }
    
      err = theAudio->readFrames(myFile);
    
      if (err != AUDIOLIB_ECODE_OK)
        {
          printf("File End! =%d\n",err);
          theAudio->stopRecorder();
          goto exitRecording;
        }
    
      if (ErrEnd)
        {
          printf("Error End\n");
          theAudio->stopRecorder();
          goto exitRecording;
        }
      }
      
      return;
    
    exitRecording:
    
      theAudio->closeOutputFile(myFile);
      myFile.close();
      
      theAudio->setReadyMode();
      theAudio->end();
      
      puts("End Recording");
      exit(1);
    }
    
    
    


  • @TE-KarlKomierowski

    Thanks for the quick response Karl. I actually ended up rewriting my code once I found Ben Eaton's code in the 'Recording at 192khz freezes' thread below, since he seems to be attempting the same this as me.

    My new program works well...for a random amount of time. Eventually it throws up the following error:

    Attention: module[4][0] attention id[1]/code[6] (objects/media_recorder/audio_recorder_sink.cpp L84)
    

    I can't seem to find a pattern for what could be causing this issue.

    Here is my code:

    #include <SDHCI.h>
    #include <Audio.h>
    #include <GNSS.h>
    
    #include <arch/board/board.h>
    
    SDClass theSD;
    AudioClass *theAudio;
    int file_count = 0;
    File myFile;
    
    bool ErrEnd = false;
    
    // When audio internal error occurs, this function will be called back.
    static void audio_attention_cb(const ErrorAttentionParam *atprm)
    {
      puts("Attention!\n");
      
      if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
        {
          ErrEnd = true;
       }
    }
    
    //Sampling Rate (16000 or 48000)
    static const uint32_t recording_sampling_rate = 48000;
    
    //Input Mic Channels (1, 2, or 4)
    static const uint8_t  recording_channel_number = 4;
    
    //Audio Bit Length (16 or 24)
    static const uint8_t  recording_bit_length = 16;
    
    //Recording Time (Seconds)
    static const uint32_t recording_time = 10;
    
    //Bytes per Second
    static const int32_t recording_byte_per_second = recording_sampling_rate *
                                                    recording_channel_number *
                                                    recording_bit_length / 8;
    //Total WAV File Size
    static const int32_t recording_size = recording_byte_per_second * recording_time;
    
    void setup()
    { 
      theAudio = AudioClass::getInstance();
    
      theAudio->begin(audio_attention_cb);
    
      puts("Initializing the Audio Library...\n");
    
      /* Select input device as microphone */
        theAudio->setRecorderMode(AS_SETRECDR_STS_INPUTDEVICE_MIC, 210); //210 = 21.0 dB Mic Gain
        theAudio->initRecorder(AS_CODECTYPE_WAV,"/mnt/spif/BIN",recording_sampling_rate,recording_bit_length,recording_channel_number);
      puts("Setting up the Recorder...\n");
    
      /* Open file for data write on SD card */
      myFile = theSD.open("Sound.wav", FILE_WRITE);
      /* Verify file open */
      if (!myFile)
        {
          printf("Error opening the WAV file...\n");
          exit(1);
        }
    
      theAudio->writeWavHeader(myFile);
      puts("Writing the WAV File Header...\n");
    
      Serial.begin(115200);
    
      theAudio->startRecorder();
      puts("Recording Started!\n");
    
    }
    
    void loop() 
    {
      err_t err;
      /* recording end condition */
      if (theAudio->getRecordingSize() > recording_size)
        {
          theAudio->stopRecorder();
          sleep(0.1);
          err = theAudio->readFrames(myFile);
    
          theAudio->closeOutputFile(myFile);
          myFile.close();
          
          file_count++;
          
          goto exitRecording;
        }
    
      /* Read frames to record in file */ 
     err = theAudio->readFrames(myFile);
    
      if (err != AUDIOLIB_ECODE_OK)
        {
          printf("File Ended! =%d\n",err);
          theAudio->stopRecorder();
          goto exitRecording;
        }
    
      if (ErrEnd)
        {
          printf("Error End\n");
          theAudio->stopRecorder();
          goto exitSketch;
        }
    
      if (file_count > 10)
        {
          goto exitSketch;
        }
      
      return;
    
    exitRecording:
        
        myFile = theSD.open(String(file_count)+".wav", FILE_WRITE);
    
        puts("Writing the WAV File Header...\n");
        theAudio->writeWavHeader(myFile);
        
        puts("Starting the Recorder...\n");
        
        theAudio->startRecorder();
        puts("Next Recording Started...\n");
        return;
    
    exitSketch:
        exit(1);
    
    }
    

    I really appreciate your help!



  • I added this snippet you mentioned in another thread with the same error:

    static void audio_attention_cb(const ErrorAttentionParam *atprm)
    {
      puts("Attention!");
    
      switch (atprm->error_code) {
        case AS_ATTENTION_CODE_INFORMATION:
        case AS_ATTENTION_CODE_WARNING    :
          ErrEnd = false;
          break;
        case AS_ATTENTION_CODE_ERROR      :
        case AS_ATTENTION_CODE_FATAL      :
        default:
          ErrEnd = true;
      }
    }
    

    Program ran fine until it got to the 7th file and got this error:

    Attention: module[4][0] attention id[1]/code[6] (objects/media_recorder/audio_recorder_sink.cpp L84)
    Attention!
    

    Then the program froze and I had to manually reset it.

    Also, I am using a 64GB SanDisk Ultra microSD Card.

    Thanks!



  • @TE-KarlKomierowski

    So I've been going through documentation and it looks like I may be running into a "FIFO Overflow" issue: AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW

    And the error information states:

    Simple fifo between application and sdk became full. Extraction speed
    may be slower than Insertion. Coordinate task priority of application
    to avoid queue remain increaseing.
    

    Also saw recommendations to increase task priority or increase the buffer size.

    I'm a bit lost and am not sure where to go from here. Would really appreciate any guidance anyone can provide...

    Thank you!


  • DeveloperWorld

    @user1388

    Hi,

    This is a known issue. I have found a temporary solution for now. Unfortunately, this requires that you build the Spresense Arduino package again. You can use this: https://github.com/sonydevworld/spresense-arduino-compatible

    Currently, when an error is detected, the Audio module stops working. However, this can be changed and when FIFO OVERFLOW is detected, samples can be dropped instead.

    As a result, the application does not finish recording, but on the other hand does not guarantee that all samples will be saved.

    Solution:

    • Find function bool AudioRecorderSink::write(const AudioRecSinkData_s &param) in the file sdk/modules/audio/objects/media_recorder/audio_recorder_sink.cpp

    • Comment line number 84.

    • Return true instead of false on line number 85.

    After the changes, the function should look like this:

    bool AudioRecorderSink::write(const AudioRecSinkData_s &param)
    {
      if (param.byte_size > 0) {
        if (CMN_SimpleFifoGetVacantSize(static_cast<CMN_SimpleFifoHandle *>
            (m_output_device_hdlr.simple_fifo_handler)) < param.byte_size)
          {
            // MEDIA_RECORDER_WARN(AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW);
            return true;
          }
    
        if (CMN_SimpleFifoOffer(static_cast<CMN_SimpleFifoHandle *>
            (m_output_device_hdlr.simple_fifo_handler),
            static_cast<const void*>(param.mh.getVa()), param.byte_size) == 0)
          {
            MEDIA_RECORDER_WARN(AS_ATTENTION_SUB_CODE_SIMPLE_FIFO_OVERFLOW);
            return false;
          }
    
        m_output_device_hdlr.callback_function(param.byte_size);
      }
      return true;
    }
    

    This is only a temporary solution. If I find other, I will let you know.