

Spresense Reference Board v2.0.1(Spresense Arduino Library
v2.0.1)のスケッチ例`Signal
Processing/LowPassSound`を実行し、シリアルモニタを開くと以下のようなログが表示され、スピーカーからノイズが再生されました。正常に動作されるためにはどのような処理が必要なのでしょうか？つい先日触り始めた機器のため右も左も分からず、困り果てています…もう一つの開発環境であるIDEバージョンで解決な場合は、ご案内をいただけると助かります。

以下の調査を通してメモリ不足を疑っておりますが、対処の方法が思いつきません。  
よろしくお願いいたします。

* * *

## 環境

windows10 Pro  
Arduino IDE 1.8.13  
Spresense Reference Board v2.0.1  
**ボード設定**  
[![画像の説明をここに入力](https://i.stack.imgur.com/4p5Zq.png)](https://i.stack.imgur.com/4p5Zq.png)

## 1.サンプルコードをそのまま実行した場合

[公式ドキュメント](https://developer.sony.com/develop/spresense/docs/arduino_tutorials_ja.html#_highpasssound_lowpasssound)を参考にDSPライブラリをSDカードにインストールした後、サンプルコードを実行した。  
以下のログが表示された。Insufficient buffer areaとあるので、メモリ不足を疑い、２を実行した。

[code]

    initialization MediaRecorder, MediaPlayer and OutputMixer
    recorder init
    player init
    recorder start
    player start
    WARNING: Insufficient buffer area.
    Error! 8 ,d04d8b0 , 1536
    WARNING: Insufficient buffer area.
    .
    .
    .同様の表示
    .
    Error! 8 ,d04d8b0 , 1536
    WARNING: Insufficient buffer area.
    
[/code]

## 2.サンプリングレートを落とした場合

再生/録音のサンプリングレートを48kHz->16kHzにし、さらにメモリの使用容量を調べるコードをmaincore,subcore1に挿入し実行した。しかしスピーカーから音すら出なかった。  
subcore1とmaincoreが起動した時点で`Free: 128 [KB]`となり、ヒープ領域がほとんど存在していない上に、

[code]

    mptask_exec() failure. -12
        Attention: module[11][0] attention id[2]/code[18] (components/decoder/decoder_component.cpp L593)
    
[/code]

とあり、おそらくDSPモジュールを読み込めなかったことが想定できる。とにかくメモリ不足が原因に見えたが、対処の方法が思いつかなかった。

以下はコードとログである。  
**ログ**

[code]

    [Sub1] Used:1024 [KB] / Free: 512 [KB] (Largest: 512 [KB])
    nitialization MediaRecorder, MediaPlayer and OutputMixer
    recorder init
    player init
    mptask_exec() failure. -12
    Attention: module[11][0] attention id[2]/code[18] (components/decoder/decoder_component.cpp L593)
    
    [Main] Used:1408 [KB] / Free: 128 [KB] (Largest: 128 [KB])
    recorder start
    Attention: module[4][0] attention id[1]/code[6] (objects/media_recorder/audio_recorder_sink.cpp L84)
    
    error! -116Attention!! Level 0x1 Code 0x6
    
[/code]

**maincore.ino**

[code]

    #include <MP.h>
    #include <MediaRecorder.h>
    #include <MediaPlayer.h>
    #include <OutputMixer.h>
    #include <MemoryUtil.h>
    
    MediaRecorder *theRecorder;
    MediaPlayer *thePlayer;
    OutputMixer *theMixer;
    
    /* Now suppot only mono channel*/
    
    /* Select mic channel number */
    const int mic_channel_num = 1;
    //const int mic_channel_num = 2;
    
    const int32_t s_buffer_size = 768 * mic_channel_num * sizeof(uint16_t);
    uint8_t s_buffer[s_buffer_size];
    bool ErrEnd = false;
    
    const int subcore = 1;
    
    struct Request {
      void *buffer;
      int  sample;
    };
    
    struct Result {
      void *buffer;
      int  sample;
    };
    
    /**
       @brief Audio attention callback
    
       When audio internal error occurc, this function will be called back.
    */
    
    static void attention_callback(const ErrorAttentionParam *atprm)
    {
      puts("Attention!");
    
      if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
      {
        ErrEnd = true;
      }
    }
    
    /**
       @brief Recorder done callback procedure
    
       @param [in] event        AsRecorderEvent type indicator
       @param [in] result       Result
       @param [in] sub_result   Sub result
    
       @return true on success, false otherwise
    */
    
    static bool mediarecorder_event_callback(AsRecorderEvent event, uint32_t result, uint32_t sub_result)
    {
      return true;
    }
    
    /**
       @brief Mixer done callback procedure
    
       @param [in] requester_dtq    MsgQueId type
       @param [in] reply_of         MsgType type
       @param [in,out] done_param   AsOutputMixDoneParam type pointer
    */
    static void outputmixer_event_callback(MsgQueId requester_dtq,
                                          MsgType reply_of,
                                          AsOutputMixDoneParam *done_param)
    {
      return;
    }
    
    /**
       @brief Mixer data send callback procedure
    
       @param [in] identifier   Device identifier
       @param [in] is_end       For normal request give false, for stop request give true
    */
    static void outmixer_rendering_callback(int32_t identifier, bool is_end)
    {
      AsRequestNextParam next;
    
      next.type = (!is_end) ? AsNextNormalRequest : AsNextStopResRequest;
    
      AS_RequestNextPlayerProcess(AS_PLAYER_ID_0, &next);
    
      return;
    }
    
    /**
       @brief Player done callback procedure
    
       @param [in] event        AsPlayerEvent type indicator
       @param [in] result       Result
       @param [in] sub_result   Sub result
    
       @return true on success, false otherwise
    */
    static bool mediaplayer_event_callback(AsPlayerEvent event, uint32_t result, uint32_t sub_result)
    {
      /* If result of "Play", restart recording (It should been stopped when "Play" requested) */
      return true;
    }
    
    /**
       @brief Player decode callback procedure
    
       @param [in] pcm_param    AsPcmDataParam type
    */
    void mediaplayer_decode_callback(AsPcmDataParam pcm_param)
    {
      /* You can imprement any audio signal process */
    
      /* Output and sound audio data */
      theMixer->sendData(OutputMixer0,
                         outmixer_rendering_callback,
                         pcm_param);
    }
    
    void setup()
    {
    
     
      /* Launch SubCore */
      int ret = MP.begin(subcore);
      if (ret < 0) {
        printf("MP.begin error = %d\n", ret);
      }
      /* receive with non-blocking */
       MP.RecvTimeout(20);
    
      /* Initialize memory pools and message libs */
      Serial.println("Init memory Library");
    
      initMemoryPools();
      createStaticPools(MEM_LAYOUT_RECORDINGPLAYER);
    
      /* start audio system */
      Serial.println("Init Audio Library");
    
      theRecorder = MediaRecorder::getInstance();
      thePlayer = MediaPlayer::getInstance();
      theMixer  = OutputMixer::getInstance();
    
      theRecorder->begin();
      thePlayer->begin();
    
      puts("initialization MediaRecorder, MediaPlayer and OutputMixer");
    
      theMixer->activateBaseband();
    
      /* Create Objects */
    
      thePlayer->create(MediaPlayer::Player0, attention_callback);
      theMixer->create(attention_callback);
    
      /* Activate Objects. Set output device to Speakers/Headphones */
    
      theRecorder->activate(AS_SETRECDR_STS_INPUTDEVICE_MIC, mediarecorder_event_callback);
      thePlayer->activate(MediaPlayer::Player0, AS_SETPLAYER_OUTPUTDEVICE_SPHP, mediaplayer_event_callback);
      theMixer->activate(OutputMixer0, outputmixer_event_callback);
    
      usleep(100 * 1000);
    
      /*
         Initialize recorder to decode stereo wav stream with 48kHz sample rate
         Search for SRC filter in "/mnt/sd0/BIN" directory
      */
      uint8_t channel;
      switch (mic_channel_num) {
        case 1: channel = AS_CHANNEL_MONO;   break;
        case 2: channel = AS_CHANNEL_STEREO; break;
        case 4: channel = AS_CHANNEL_4CH;    break;
      }
      
      //const auto codec_path = "/mnt/spif/BIN";
    
      theRecorder->init(AS_CODECTYPE_LPCM, channel, AS_SAMPLINGRATE_16000, AS_BITLENGTH_16, 0);//サンプリングレートを変更したらどうにかなる？
      theRecorder->setMicGain(180);
      puts("recorder init");
      thePlayer->init(MediaPlayer::Player0, AS_CODECTYPE_WAV,AS_SAMPLINGRATE_16000, channel);
      puts("player init");
    
      /* Start Recorder */
    
      theMixer->setVolume(0, 0, 0);
      
      #if 1
        //memcheck
        int usedMem, freeMem, largestFreeMem;
      
        MP.GetMemoryInfo(usedMem, freeMem, largestFreeMem);
      
        MPLog("Used:%4d [KB] / Free:%4d [KB] (Largest:%4d [KB])\n",
              usedMem / 1024, freeMem / 1024, largestFreeMem / 1024);
      #endif 
    }
    
    typedef enum e_appState {
      StateReady = 0,
      StatePrepare,
      StateRun
    } appState_t;
    
    void loop()
    {
      static appState_t state = StateReady;
    
      int8_t   sndid = 100; /* user-defined msgid */
      int8_t   rcvid = 0;
      int      read_size;
      int      ret;
    
      static Request  request;
      static Result*  result;
      
      switch (state) {
        case StateReady:
          {
          /* Start recording */
          theRecorder->start();
          puts("recorder start");
          state = StatePrepare;
          break;
          }
        case StatePrepare:
        {
          static int pre_cnt = 0;
          err_t err = theRecorder->readFrames(s_buffer, s_buffer_size, &read_size);
    
          if (err != 0) { printf("Error! %x ,%x , %d\n",err,request.buffer,request.sample); }
    
          if (read_size > 0)
          {
            request.buffer  = s_buffer;
            request.sample = read_size/ sizeof(uint16_t) / mic_channel_num;
            MP.Send(sndid, &request, subcore);
    
            if (pre_cnt < 2) {
              pre_cnt++;
              break;
            }
    
            /* Receive sound from SubCore */
            int ret = MP.Recv(&rcvid, &result, subcore);
            if (ret >= 0) {
              if (result->sample != 768) { break;}
              thePlayer->writeFrames(MediaPlayer::Player0, result->buffer, result->sample*2);
              pre_cnt++;
            } else {
              printf("error! %d", ret);
              exit(1);
            }
          } else {
            break;
          }
    
          if (pre_cnt > 10) {
            puts("player start");
            thePlayer->start(MediaPlayer::Player0, mediaplayer_decode_callback);
            pre_cnt = 0;
            state = StateRun;
          }
          break;
        }
    
        case StateRun:
        {
          err_t err = theRecorder->readFrames(s_buffer, s_buffer_size, &read_size);
    
          if (err != 0) {printf("Error! %x ,%x , %d\n",err,request.buffer,read_size);}
          if (read_size > 0)
          {
            request.buffer  = s_buffer;
            request.sample = read_size / sizeof(uint16_t) / mic_channel_num;
            MP.Send(sndid, &request, subcore);
    
            /* Receive sound from SubCore */
            ret = MP.Recv(&rcvid, &result, subcore);
            if (ret >= 0) {
              if (result->sample != 768) {break;}
              thePlayer->writeFrames(MediaPlayer::Player0,result->buffer, result->sample*2);
            } else {
              printf("error! %d", ret);
              exit(1);
            }
          } else {
            break;
          }
          break;
        }
        default:
        {
          puts("error!");
          exit(1);
        }
      }
    }
    
[/code]

**subcore.ino**

[code]

    #include <MP.h>
    
    #include "IIR.h"
    
    /* Use CMSIS library */
    #define ARM_MATH_CM4
    #define __FPU_PRESENT 1U
    #include <cmsis/arm_math.h>
    
    /* channel number */
    const int g_channel = 1;
    
    IIRClass LPF;
    
    /* Allocate the larger heap size than default */
    
    USER_HEAP_SIZE(64 * 1024);
    
    /* MultiCore definitions */
    
    struct Request {
      void *buffer;
      int  sample;
    };
    
    struct Result {
      void *buffer;
      int  sample;
    };
    
    void setup()
    {
      int ret = 0;
    
      /* Initialize MP library */
      ret = MP.begin();
      if (ret < 0) {
        errorLoop(2);
      }
      /* receive with non-blocking */
    //  MP.RecvTimeout(MP_RECV_POLLING);
      MP.RecvTimeout(100000);
      LPF.begin(TYPE_LPF,g_channel,1000,sqrt(0.5));
        #if 1
        //memcheck
        int usedMem, freeMem, largestFreeMem;
      
        MP.GetMemoryInfo(usedMem, freeMem, largestFreeMem);
      
        MPLog("Used:%4d [KB] / Free:%4d [KB] (Largest:%4d [KB])\n",
              usedMem / 1024, freeMem / 1024, largestFreeMem / 1024);
      #endif 
    }
    
    #define RESULT_SIZE 4
    void loop()
    {
      int      ret;
      int8_t   sndid = 10; /* user-defined msgid */
      int8_t   rcvid;
      Request  *request;
      static Result result[RESULT_SIZE];
    
      static q15_t pDst[FRAMSIZE];
      static q15_t out_buffer[RESULT_SIZE][FRAMSIZE*g_channel];
      static int pos=0;
    
      /* Receive PCM captured buffer from MainCore */
      ret = MP.Recv(&rcvid, &request);
      if (ret >= 0) {
          LPF.put((q15_t*)request->buffer,request->sample);
      }else{
          puts("error!");
          return;
      }
    
      int cnt = 0;
      while (!LPF.empty(0)) {
        for (int i = 0; i < g_channel; i++) {
          cnt = LPF.get(pDst,i);
          /* support only mono channel */
          memcpy(&out_buffer[pos][0],pDst,cnt*2);
        }
    
        result[pos].buffer = MP.Virt2Phys(&out_buffer[pos][0]);
        result[pos].sample = cnt;
    
        ret = MP.Send(sndid, &result[pos],0);
        pos = (pos+1)%RESULT_SIZE;
        if (ret < 0) {
          errorLoop(1);
        }
      }
    }
    
    void errorLoop(int num)
    {
      int i;
    
      while (1) {
        for (i = 0; i < num; i++) {
          ledOn(LED0);
          delay(300);
          ledOff(LED0);
          delay(300);
        }
        delay(1000);
      }
    }
    
[/code]


CC BY-SA 4.0
2020-06-26T09:11:12.940
68029
2020-08-14T02:08:45.927
40834
question
spresense arduino
Spresenseのサンプルコード "Signal Processing/LowPassSound"を実行しても正常に動作せず、mptask_exec() failure. -12と表示される。


自分が実行したところ、特にノイズにはなりませんでした。

ただ、このエラーは、確かに出ますね。

WARNING: Insufficient buffer area.  
Error! 8 ,d04d8b0 , 1536

でも、このエラー出ても動作するようです。  
WARNING なので、警告程度なのでしょうか。


CC BY-SA 4.0
2020-06-26T12:22:18.823
68034
2020-06-26T12:22:18.823
32281
68029
answer