首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将short[]从SoundTouch音频库转换为回放

将short[]从SoundTouch音频库转换为回放
EN

Stack Overflow用户
提问于 2014-01-05 04:39:31
回答 1查看 1.4K关注 0票数 1

我试图在安卓应用程序中使用SoundTouch C++库来实现音频速度和音高变化。我已经成功地将一个Java数组(从一个byte[] )推到JNI中,返回它,然后用一个AudioTrack回放它。

下一步是尝试将示例byte[]推送到SoundTouch管道中。我已经剖析了库中包含的SoundStretch控制台程序的源代码,并试图对其进行调整。我正在使用一个立体声,16位源,用于测试目的.

使用当前的临时设置,我忽略了RIFF头,并将其与.wav数据一起转换,因为Java对象不需要读取标头,它只播放原始的AudioTrack。在不通过byte[]发送的情况下播放原始的SoundTouch只会导致小的单击标题所在的位置。

在通过SoundTouch管道发送后,我正在播放白噪声,音频的开头应该在那里。我想我在write()函数的末尾出现了问题,在此,我要对已签名的字符进行简短的转换。在这里,控制台应用程序正在写入文件,而不是推送到向量:

代码语言:javascript
运行
复制
int res = (int)fwrite(temp, 1, numBytes, fptr);

我已经阅读了fwrite的文档,但是我不知道如何正确地在char[]中获得这些信息,而不是写入文件。我知道我正在与演员失去信息,但我不知道如何纠正它。

如果有人有额外的动机,可以在这里找到SoundStretch源代码:http://www.surina.net/soundtouch/sourcecode.html

代码语言:javascript
运行
复制
extern "C" DLL_PUBLIC jbyteArray 
Java_net_surina_soundtouch_SoundTouch_getMutatedBytes
(JNIEnv *env, jobject thiz, jbyteArray input, jint length)
{
    const int BUFF_SIZE = 2048000;

    SoundTouch soundTouch;

    jboolean isCopy;
    jbyte* ar = env->GetByteArrayElements(input, &isCopy);

    signed char* cBufferIn = (signed char*)ar;

    SAMPLETYPE* fBufferIn = new SAMPLETYPE[length];
    vector<signed char> fBufferOut;

    //converts the chars to floats per the SoundTouch console app.
    convertInput16(cBufferIn, fBufferIn, length); 

    //channels, sampling rate, speed, pitch change
    setup(&soundTouch, 2, 44100, 1.0, 0);

    //transform floats from fBufferIn to fBufferout
    process(&soundTouch, fBufferIn, fBufferOut, BUFF_SIZE); 

    signed char* res = &fBufferOut[0];

    jbyteArray result = env->NewByteArray(length);
    env->SetByteArrayRegion(result, 0, fBufferOut.size(), res);

    LOGV("fBufferOut Size: %d", fBufferOut.size());

    delete[] fBufferIn;

    return result;
}

程序():

代码语言:javascript
运行
复制
static void process(SoundTouch* soundTouch, SAMPLETYPE* fBufferIn, vector<signed char>& fBufferOut, int BUFF_SIZE)
{
    int nSamples = BUFF_SIZE / 2; //2 bytes per sample, using 16 bit sample for testing
    int buffSizeSamples = BUFF_SIZE / 2; //2 channel stereo

    soundTouch->putSamples(fBufferIn, nSamples);

    do
    {
        nSamples = soundTouch->receiveSamples(fBufferIn, buffSizeSamples);
        write(fBufferIn, fBufferOut, nSamples / 2); //2 channels
    } while (nSamples != 0);

    soundTouch->flush();

    do
    {
        nSamples = soundTouch->receiveSamples(fBufferIn, buffSizeSamples);
        write(fBufferIn, fBufferOut, nSamples / 2);
        LOGV("NUMBER OF SAMPLES: %d", nSamples);
    } while (nSamples != 0);
}

写():

代码语言:javascript
运行
复制
static void write(const float *bufferIn, vector<signed char>& bufferOut, int numElems)
{
    int numBytes;
    int bytesPerSample;

    if (numElems == 0) return;

    bytesPerSample = 16 / 8; //16 bit test sample / bits in a byte
    numBytes = numElems * bytesPerSample;
    short *temp = (short*)getConvBuffer(numBytes);

    switch (bytesPerSample)
    {

    case 2: //16 bit encoding per the SoundStretch console app
    {
              short *temp2 = (short *)temp;
              for (int i = 0; i < numElems; i++)
              {
                  short value = (short)saturate(bufferIn[i] * 32768.0f, -32768.0f, 32767.0f); //magic to me
                  temp2[i] = value; //works for little endian only.
              }
              break;
    }

    default:
        assert(false);
    }

    for (int i = 0; i < numElems; ++i)
    {
        bufferOut.push_back((signed char)temp[i]); //I think my problem is here.
    }

    delete[] temp;

    //bytesWritten += numBytes;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-05 06:01:15

我只需要获取char[]中的所有信息:

代码语言:javascript
运行
复制
for (int i = 0; i < numElems; ++i)
{
    bufferOut.push_back(temp[i] & 0xff);
    bufferOut.push_back((temp[i] >> 8) & 0xff);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20930127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档