【问题标题】:Converting mono to stereo sound将单声道转换为立体声
【发布时间】:2013-10-11 07:27:57
【问题描述】:

我正在尝试将 16 位单声道声音转换为立体声。声音存储为字节数组,因此据我了解,这意味着我一次复制两个字节。

我这样做对吗?我生成的代码改变了频率。

编辑:

我已成功生成单音并将其存储在byte [] generatedSnd

播放单声道声音(工作):

    AudioTrack audioTrack = null;                                   // Get audio track
    try {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, (int)numSamples*2,
                AudioTrack.MODE_STATIC);
        audioTrack.setStereoVolume(0f, 1f);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);     // Load the track
        audioTrack.play();                                          // Play the track
    }
    catch (Exception e){ }

转换成立体声:

    int monoByteArrayLength = generatedSnd.length;
    byte [] stereoGeneratedSnd = new byte[monoByteArrayLength * 2];

    stereoGeneratedSnd[0] = generatedSnd[0];
    stereoGeneratedSnd[2] = generatedSnd[0];

    for (int x=1; x<monoByteArrayLength; x+=2) {

        stereoGeneratedSnd[x*2-1] = generatedSnd[x];
        stereoGeneratedSnd[x*2+1] = generatedSnd[x];

        if (x+1 < monoByteArrayLength) {
            stereoGeneratedSnd[x*2] = generatedSnd[x+1];
            stereoGeneratedSnd[x*2+2] = generatedSnd[x+1];
        }
    }

    AudioTrack audioTrack = null;                                   // Get audio track
    try {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT, (int)numSamples*2,
                AudioTrack.MODE_STATIC);
        audioTrack.setStereoVolume(0f, 1f);
        audioTrack.write(stereoGeneratedSnd, 0, stereoGeneratedSnd.length);     // Load the track
        audioTrack.play();                                          // Play the track
    }
    catch (Exception e){ }

我想做的是只从一个频道播放声音

【问题讨论】:

  • 请添加更多上下文。这是什么格式?你用什么库来播放文件?什么语言?还有一个关于常识的问题:播放流的逻辑应该如何知道这是单声道文件,每 2 个样本相同,还是假立体声文件?它不能只是“猜测”......应该有一些元数据,描述流,不是吗?

标签: android audio audiotrack


【解决方案1】:

一次复制两个字节是故意的吗? 16bit PCM Wave 格式的立体声模式需要:

DATA[ ] : [1st byte from Chanel 1], [1st byte from Chanel 2], [2nd byte from Chanel 1], [2nd byte from Chanel 2]...

所以如果你想将单声道转换为立体声,你的数组应该是:

Mono   : 0, 1, 2, 3 ...
Stereo : 0, 0, 1, 1, 2, 2, 3, 3 ...

如果你只想要一个频道

Stereo : 0, 0, 1, 0, 2, 0, 3, 0 ...

【讨论】:

    【解决方案2】:

    加倍算法的输出是0, 1, 2, 1, 2, 3, 4, 3, 4, 5, 0, 5

    一种更简单(且正确)的加倍方法是:

    for (int i = 0; i < monoByteArrayLength; i += 2) {
        stereoGeneratedSnd[i*2+0] = generatedSnd[i];
        stereoGeneratedSnd[i*2+1] = generatedSnd[i+1];
        stereoGeneratedSnd[i*2+2] = generatedSnd[i];
        stereoGeneratedSnd[i*2+3] = generatedSnd[i+1];
    }
    

    输出:0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5

    【讨论】:

    • 哪里不对?另外,请记住,当您在静态模式下使用 AudioTrack 时,缓冲区大小参数指定 “将为此实例播放的声音的最大大小 [in bytes]” .
    • 缓冲区大小固定。我认为这只会影响持续时间而不是频率,但我们在这里。谢谢。
    猜你喜欢
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2017-01-22
    • 1970-01-01
    相关资源
    最近更新 更多