跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • Online Tools
  • 用户
  • 群组
折叠
品牌标识

D2Learn Forums

  1. 主页
  2. General Discussion | 综合讨论
  3. 关于sonic实现音频变速不变调的问题

关于sonic实现音频变速不变调的问题

已定时 已固定 已锁定 已移动 General Discussion | 综合讨论
问题求助c++ffmpegsdlsonic
11 帖子 3 发布者 121 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • SPeakS 离线
    SPeakS 离线
    SPeak d2learn-dev
    编写于 最后由 编辑
    #2

    可以提供一个最小可复现示例项目的zip或git仓库链接, 以及崩溃时的调用栈...
    (大面积代码更建议用文本, 截图不方便)

    1 条回复 最后回复
    0
    • hammerersH 离线
      hammerersH 离线
      hammerers
      编写于 最后由 编辑
      #3

      我写了一个能够复现该问题的项目git@github.com:hammerers/sonic_ffmpeg_sdl_audio_player.git

      1 条回复 最后回复
      0
      • SPeakS 离线
        SPeakS 离线
        SPeak d2learn-dev
        编写于 最后由 编辑
        #4

        @hammerers 是只要speed不是1就会报错 小于1和大于1有区别吗, crash的时候调用栈有吗


        补充仓库地址: https://github.com/hammerers/sonic_ffmpeg_sdl_audio_player

        1 条回复 最后回复
        0
        • hammerersH 离线
          hammerersH 离线
          hammerers
          编写于 最后由 编辑
          #5

          debug的时候有三个地方会中断,甚至有时候可以播放出变速的声音只是是全损音质,debug的调用栈显示的都是SDL的dll,或者在sonic.c
          Screenshot 2025-08-15 175323.png

          1 条回复 最后回复
          0
          • hammerersH 离线
            hammerersH 离线
            hammerers
            编写于 最后由 编辑
            #6

            speed大于小于一都会有这种情况

            1 条回复 最后回复
            0
            • SPeakS 离线
              SPeakS 离线
              SPeak d2learn-dev
              编写于 最后由 编辑
              #7

              这里往stream里写数据的时候没有加filled的偏移, 导致重复把数据写到了buff的开头部分

              image.png

              1 条回复 最后回复
              0
              • hammerersH 离线
                hammerersH 离线
                hammerers
                编写于 最后由 编辑
                #8
                此回复已被删除!
                1 条回复 最后回复
                0
                • hammerersH 离线
                  hammerersH 离线
                  hammerers
                  编写于 最后由 编辑
                  #9

                  天哪,太粗心了,谢谢!尽管修复了它之后还是会崩溃

                  1 条回复 最后回复
                  0
                  • hammerersH 离线
                    hammerersH 离线
                    hammerers
                    编写于 最后由 编辑
                    #10
                    此回复已被删除!
                    1 条回复 最后回复
                    0
                    • Cat-GuijunC 离线
                      Cat-GuijunC 离线
                      Cat-Guijun
                      编写于 最后由 编辑
                      #11

                      hi,友友有解决这个情况吗,我也是当speed不为一时就报错了,我完全不知道如何查找崩溃,找了一天了,下面是我的代码:
                      void AudioDecodeThread::run()
                      {
                      // 加入sonic
                      // 初始化部分:先创建一个流
                      sonicStream stream = sonicCreateStream(m_videoPlayControl->m_audioCodecCtx->sample_rate, 2);
                      if (!stream)
                      {
                      m_videoPlayControl->m_eventHandler->onVideoPlayerError(0, "sonicCreateStream error!");
                      }

                          if (!initSwrCtx())
                          {
                              m_videoPlayControl->m_eventHandler->onVideoPlayerError(0, "initSwrCtx error");
                              return;
                          }
                      
                          while (true)
                          {
                              if (m_videoPlayControl->m_currentState == State::STOP)
                              {
                                  break;
                              }
                              else if (m_videoPlayControl->m_currentState == State::PAUSE)
                              {
                                  std::this_thread::sleep_for(std::chrono::milliseconds(10));
                                  continue;
                              }
                      
                              AVPacket *pkt = m_videoPlayControl->m_audioPacketQueue.pop();
                              if (pkt == nullptr)
                              {
                                  if (m_videoPlayControl->m_isReadFinished)
                                  {
                                      break;
                                  }
                                  continue;
                              }
                      
                              if (memcmp(pkt->data, FLUSHDATA, strlen(FLUSHDATA)) == 0)
                              {
                                  avcodec_flush_buffers(m_videoPlayControl->m_audioCodecCtx);
                                  av_packet_free(&pkt);
                                  continue;
                              }
                      
                              int ret = avcodec_send_packet(m_videoPlayControl->m_audioCodecCtx, pkt);
                              if (ret < 0)
                              {
                                  char errbuf[1024] = { 0 };
                                  av_strerror(ret, errbuf, sizeof(errbuf));
                                  fprintf(stderr, "avcodec_send_packet: %s (error pts: %d)\n", errbuf, pkt->pts);
                                  av_packet_free(&pkt);
                                  continue;
                              }
                      
                              AVFrame *frame = av_frame_alloc();
                              while (avcodec_receive_frame(m_videoPlayControl->m_audioCodecCtx, frame) == 0)
                              {
                                  // 读取frame, swr转换, 放到frameQueue里面去
                                  int inSamples = frame->nb_samples;
                                  // int outSamples = av_rescale_rnd(inSamples, 1, 1, AV_ROUND_UP);
                      
                                  // 废除手动分配的 audioBuffer,改用 resampleFrame 内部缓冲区
                                  AVFrame *resampleFrame = av_frame_alloc();
                                  resampleFrame->format = AV_SAMPLE_FMT_S16;
                                  av_channel_layout_default(&resampleFrame->ch_layout, 2); // 双声道
                                  resampleFrame->sample_rate = frame->sample_rate;         // 正确设置采样率
                                  resampleFrame->nb_samples = inSamples;
                      
                                  // 让 FFmpeg 自动分配缓冲区(确保地址和大小正确)
                                  if (av_frame_get_buffer(resampleFrame, 0) < 0)
                                  {
                                      av_frame_free(&resampleFrame);
                                      continue;
                                  }
                      
                                  int len = swr_convert(m_swrCtx, resampleFrame->data, resampleFrame->nb_samples, (const uint8_t **)frame->data, inSamples);
                      
                                  // 加入sonic
                      
                                  sonicSetSpeed(stream, m_videoPlayControl->m_speed);
                                  // 4. 写入音频数据到Sonic ,这里的bug
                      
                                  short *valid_audio_data = (short *)resampleFrame->data[0];
                                  int total_samples = len; // 单声道总样本数
                      
                                  std::cout << len << std::endl;
                      
                                  ret = sonicWriteShortToStream(stream, valid_audio_data, total_samples);
                                  if (ret == 0)
                                  {
                                      m_videoPlayControl->m_eventHandler->onVideoPlayerError(0, "sonicWriteShortToStream error");
                                      continue;
                                  }
                      
                                  int availableSamples = sonicSamplesAvailable(stream); //
                                  if (availableSamples <= 0)
                                  {
                                      continue;
                                  }
                      
                                  // 根据实际需要的样本数分配缓冲区
                                  short *output_pcm = new short[availableSamples * 2];
                                  int samples = sonicReadShortFromStream(stream, output_pcm, availableSamples);
                                  if (samples <= 0)
                                  {
                                      delete[] output_pcm;
                                      av_frame_free(&resampleFrame);
                                      continue;
                                  }
                      
                                  std::cout << inSamples << "---" << len << "---" << availableSamples << "---" << samples << std::endl;
                      
                                  PCMFrame *pcm = new PCMFrame();
                                  pcm->setBuffer((uint8_t *)output_pcm, samples * 4);
                                  pcm->setPts(frame->pts);
                                  pcm->setSampleRate(frame->sample_rate);
                                  m_videoPlayControl->m_audioFrameQueue.push(pcm);
                      
                                  delete[] output_pcm;
                                  av_frame_free(&resampleFrame);
                              }
                              av_frame_free(&frame);
                              av_packet_free(&pkt);
                          }
                          sonicDestroyStream(stream);
                      }
                      
                      1 条回复 最后回复
                      0

                      • 登录

                      • 没有帐号? 注册

                      • 登录或注册以进行搜索。
                      d2learn forums Powered by NodeBB
                      • 第一个帖子
                        最后一个帖子
                      0
                      • 版块
                      • 最新
                      • 标签
                      • 热门
                      • Online Tools
                      • 用户
                      • 群组