【问题标题】:Best practice: Where to resample PCM and which tool?最佳实践:在哪里重新采样 PCM 以及使用哪个工具?
【发布时间】:2012-06-28 14:25:33
【问题描述】:

我开发了一个内核模块 (Android),它为我提供:

PCM
16-bit
48000 Hz
2 channel

我想用 java 将它流式传输到 Apple 的 Airport Express (AEX)。

AEX 需要 44.1 kHz PCM,因此我必须重新采样 PCM 流。

我有以下几种可能,但哪种最好?

1。使用 C 程序“raop_play”(raop-play 的一部分)

advantages: 
            high-performant due to native C
            already uses libsamplerate to resample wav, mp3, ogg, flac, aac, pls
            openssl as static library
            usable via command-line from my java-program via Runtime.exec()

disadvantages:
            I am relative new to C
            overloaded: I don't need wav, mp3.. only PCM
            many dependencies with GPL-libraries which I have to compile for Android
            only supports PCM already with 44.1 kHz, no resampling for PCM implemented yet 
            -> have to implement resampling for PCM

2。在 Java 中重新采样和流式传输(使用 libresample JNI-bridge

advantages: 
            I CAN java :)
            middle-performant due to resamling in C , but streaming in java
            just one dependency to LGPL-library
            no Runtime.exec() needed

disadvantages:
            needs [bouncycastle][3] for AES which is a bit larger than openssl
            less performant than solution #1 (but maybe fast enough)

3。内核模块中已经重新采样

advantages: 
            most performant
            no resampling at higher level

disadvantages:
            I am relative new to C
            Is it possible to use libsamplerate or libresample in kernel-space?!

【问题讨论】:

    标签: java c java-native-interface kernel-module resampling


    【解决方案1】:

    我是个 Java 爱好者,但这个任务(尤其是在 CPU 受限的设备上,比如手持设备)急需 C。我建议简单地使用 libsamplerate。它有一个简单的 API,即使您是 C 新手,也可以通过谷歌搜索找到大量示例。

    当然,基于 java 的解决方案可以而且会起作用,只是因为你是 C 的新手,所以对用户消耗电池似乎并不礼貌 :)

    编辑: 我可能会有点自相矛盾,但即使性能是一个严重的问题,我也会避免在内核空间中做任何事情,除非我非常了解内核和硬件 .鉴于此,我将使用与 libsamplerate 相关联的用户空间程序。经过一番谷歌搜索后,我找到了这个例子(注意输出是插孔接口,显然它对你来说必须不同

    #include <jack/jack.h>
    #include <samplerate.h>
    
    int channels;
    float data_samplerate;
    
    
    /////////////////////////////////////////////////////
    /////////////////////////////////////////////////////
    void getDasData(float **dst,int num_frames){
    /* Provide sound data here, and only here. */
    }
    /////////////////////////////////////////////////////
    /////////////////////////////////////////////////////
    
    
    
    long getDasResampledData_callback(void *cb_data, float **data){
      static float ret[1024];
      static float ret3[1024];
      static float *ret2[2]={&ret[0],&ret[512]};
      getDasData(ret2,512);
      for(int i=0;i<512;i++){
        ret3[i*2]=ret2[0][i];
        ret3[i*2+1]=ret2[1][i];
      }
      *data=&ret3[0];
      return 512;
    }
    
    void getDasResampledData(float **dst,int num_frames){
      double ratio=samplerate/getSourceRate();
      float outsound[num_frames*2];
      long read=src_callback_read(dassrc_state,ratio,num_frames,outsound);
      //fprintf(stderr,"read: %d, num_frames: %d\n",read,num_frames);
      for(int i=0;i<read;i++){
          dst[0][i]=outsound[i*2];
          dst[1][i]=outsound[i*2+1];
      }
      if(read<num_frames){
        float *newdst[2]={dst[0]+read,dst[1]+read};
        getDasResampledData(newdst,num_frames-read);
      }
    }
    
    
    static int process (jack_nframes_t nframes, void *arg){
      int ch;
      sample_t *out[channels];
    
      for(ch=0;ch<channels;ch++){
        out[ch]=(sample_t*)jack_port_get_buffer(ports[ch],nframes);
      }
    
      if( (fabs(data_samplerate - jack_samplerate)) > 0.1)
        getDasResampledData(out,numSamples);
      else
        getDasData(outputChannelData,numSamples);
      return;
    
      audioCallback(NULL,0,out,channels,nframes);
    }
    
    int main(){
      dassrc_state=src_callback_new(getDasResampledData_callback,SRC_QUALITY,2,NULL,NULL);
      jack_set_process_callback(client, process,NULL);
    }
    

    来自http://old.nabble.com/Example-of-using-libresample-with-jack-td8795847.html

    这个例子看起来很简单,希望你能用。

    【讨论】:

    • 我终于混合了解决方案 #1 和 #2:我已经在用户空间的程序中使用“libresample”实现了下采样。高性能。我对 2 个频道感到头疼,但解决了它:)。谢谢!
    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多