75350


SpresenseでMP3を連続再生したいのですが、連続再生をしていると途中で以下のエラーが出てきてしまいます。

[![](https://i.stack.imgur.com/f8mMB.png)](https://i.stack.imgur.com/f8mMB.png)

ちなみに書いているコードはこちらです。

[code]

    #include <Audio.h>
    #include <SDHCI.h>
    
    SDClass SDcard;
    AudioClass *audio;
    File dir, file;
    err_t err;
    int TrackCounter = 0; // MP3 Playing Track Counter.
    bool PlayingState = false; // true MP3 Playing.
    bool setPlayState = false;
    int AudioVolume = -220;
    bool ErrEnd = false;
    
    
    static void audio_attention_cb(const ErrorAttentionParam *atprm) {
      puts("Attention!");
      if (atprm->error_code >= AS_ATTENTION_CODE_WARNING) {
          ErrEnd = true;
       }
    }
    
    void setup() {
      SDcard.begin();
      // Setup AudioPlayer.
      // DSP File -> SPIFLASH.
      audio = AudioClass::getInstance();
      audio->begin(audio_attention_cb);
      audio->setRenderingClockMode(AS_CLKMODE_NORMAL);
      audio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);
      audio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/spif/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);
      Serial.begin(115200); // Debug
    }
    
    /* Audio Volume UP */
    void AudioVolume_UP() {
      if (AudioVolume >= -220) { // Volume Max Value
        Serial.println("Volume is Max value!");
      } else {
        AudioVolume = AudioVolume + 20;
        Serial.println(AudioVolume);
        audio->setVolume(AudioVolume);
      }
    }
    /* Audio Volume Down */
    void AudioVolume_DOWN() {
      if (AudioVolume <= -700) { // Volume Min Value
        Serial.println("Volume is Min value!");
      } else {
        AudioVolume = AudioVolume - 20;
        Serial.println(AudioVolume);
        audio->setVolume(AudioVolume);
      }
    }
    
    void NextMusicPlay() {
      if (PlayingState == true) {
        audio->stopPlayer(AudioClass:: Player0);
        PlayingState = false;
        AudioPlay_fop();
      } else {
        /* - */
      }
    }
    
    void AudioStopStartPlay() {
      if (PlayingState == true) {
        audio->stopPlayer(AudioClass:: Player0, AS_STOPPLAYER_ESEND);
        PlayingState = false;
        setPlayState = false;
      } else {
        if (ErrEnd) {
          ErrEnd = false;
          audio->begin(audio_attention_cb);
          audio->setRenderingClockMode(AS_CLKMODE_NORMAL);
          audio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);
          audio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/spif/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);
          usleep(40000);
        }
        AudioPlay_fop();
        setPlayState = true;
      }
    }
    
    /* AudioPlay, File Open */
    void AudioPlay_fop() {
      if (!dir) {
        dir = SDcard.open("/Musics");
      }
      file = dir.openNextFile();
      if (!file) {
        dir.close();
        dir = SDcard.open("/Musics");
        file = dir.openNextFile();
        TrackCounter = 0;
      }
      // puts(file.name());
      audio->writeFrames(AudioClass:: Player0, file);
      usleep(40000);
      audio->startPlayer(AudioClass:: Player0);
      PlayingState = true;
      TrackCounter ++;
      String trstr = "Track: " + String(TrackCounter);
      Serial.println(trstr);
      audio->setVolume(AudioVolume);
    }
    
    void loop() {
      if (setPlayState == true) {
        /*if (!file) {
          AudioPlay_fop();
        }*/
        err = audio->writeFrames(AudioClass:: Player0, file);
        if (err == AUDIOLIB_ECODE_FILEEND) {
          audio->stopPlayer(AudioClass:: Player0, AS_STOPPLAYER_ESEND);
          PlayingState = false;
          AudioPlay_fop();
        }
        if (ErrEnd) {
          audio->stopPlayer(AudioClass:: Player0);
          PlayingState = false;
          setPlayState = false;
          file.close();
          audio->setReadyMode();
          audio->end();
        }
        usleep(1000);
      } else {
        /* - */
      }
      
      if (Serial.available() > 0){ // Test Mode.
        Serial.println("read");
        String serstr = Serial.readString();
        serstr.trim();
        if (serstr.equals("up") == true) {
          AudioVolume_UP();
        }
        if (serstr.equals("down") == true) {
          AudioVolume_DOWN();
        }
        if (serstr.equals("ps") == true) {
          AudioStopStartPlay();
        }
        if (serstr.equals("next") == true) {
          NextMusicPlay();
        }
      }
    }
    
[/code]

いろいろ検索してみたのですが、解決方法が分かりません...  
なにか間違っているところなどありましたら教えてください。お願いしますm(_ _)m


CC BY-SA 4.0
2021-04-08T01:16:52.257
75154
2021-04-17T22:56:19.180
44687
question
spresense
SpresenseでMP3を連続再生時にエラーが出る


添付されているエラーは、ファイルの読み出し速度が間に合わないために発生するものですね。  
MP3だとすると、それほど、読み出し速度が厳しいとは思えないのですが、まずは、

usleep(1000);

をやめてみてはどうでしょうか？

ダメなら、

[code]

      err_t setPlayerMode(
      uint8_t device,          /**< Select output device. AS_SETPLAYER_OUTPUTDEVICE_SPHP or 
                                    AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT. */
      uint8_t sp_drv,          /**< Select audio speaker driver mode. AS_SP_DRV_MODE_LINEOUT or
                                    AS_SP_DRV_MODE_1DRIVER or AS_SP_DRV_MODE_2DRIVER or AS_SP_DRV_MODE_4DRIVER */
      uint32_t player0bufsize, /**< Buffer size of player 0. Must be n > 0. */
      uint32_t player1bufsize  /**< Buffer size of player 1. Must be n > 0. */
    
[/code]

);

でバッファサイズが変えられるので、変えてみてはどうでしょう？

※見た感じ、(1024 _2_ 8)*10 で十分大きいから、違うかな…。

後、他のスレッドにもあるように、SDカードのメーカと状態にも依存するので、  
出来れば、SDカードを、一度、物理フォーマットすることをお勧めします。


CC BY-SA 4.0
2021-04-09T19:32:13.033
75186
2021-04-09T19:32:13.033
32281
75154
answer


もうちょっと、添付のコードをじっくり動かしてみました。  
問題が発生するのは、曲の停止から、次の曲の再開の部分になりますね。

更に、デバッグコードを入れて確認したところ、  
その中のどのタイミングでエラーが発生するか？というと、  
ストップ処理が終わった後で、次のファイルを再生を開始した直後になるようです。

puts(file.name());  
audio->writeFrames(AudioClass:: Player0, file);  
usleep(40000);  
audio->startPlayer(AudioClass:: Player0);  
PlayingState = true;

この直後に出ています。

すなわち、

audio->writeFrames(AudioClass:: Player0, file);

で書き込めていないのですが、良く調べてみると、  
fileがFILE_ENDだと判断して何も書きこまずエラーになっています。

で、なぜ、このようになるのか？というと、理由はわからないですが、

file = dir.openNextFile();

で、ファイルが存在しているにもかかわらずエラーになり、

if (!file) {

の処理に入ってしまいます。  
その後、close/openしたとしても、available にならず、  
読み込めないようです。

ただ、こうなってしまう原因と、こうなったときの回避方法はちょっと思い当たらないのですが…。

（追記）  
なんとなくですが、ある回数以上に曲の切り替えが起こると問題が発生する気がします。  
メモリリークなどで破壊が起きているのでしょうか…。

と、いうところで気が付きました。

void AudioPlay_fop() {  
if (!dir) {  
dir = SDcard.open("/Musics");  
}  
file.close();  
file = dir.openNextFile();  
if (!file.available()) {

というとこで、

file.close();

がないため、openできる数の限界がきて、以降、何をやってもfile操作ができないみたいです。  
ここに、closeを入れると動作し続けました。


CC BY-SA 4.0
2021-04-17T17:37:19.500
75350
2021-04-17T22:56:19.180
2021-04-17T22:56:19.180
32281
32281
75154
answer