2014-01-05 4 views
0

Я пытаюсь использовать библиотеку SoundTouch C++ для скорости звука и изменения высоты тона в приложении для Android. Я успешно нажал массив байтов Java [] из (.wav) через JNI, вернул его и воспроизвел с AudioTrack.Преобразование короткой [] из звуковой библиотеки SoundTouch для воспроизведения

Следующим шагом является попытка выталкивать образец байта [] через конвейер SoundTouch. Я разобрал источник программы SoundStretch, включенной в библиотеку, и попытался ее адаптировать. Я использую стерео, 16-разрядный источник для тестирования.

С моей текущей временной настройкой я игнорирую заголовок RIFF и преобразовываю его вместе с данными .wav, потому что объект Java AudioTrack не нуждается в чтении заголовка, он просто воспроизводит raw PCM. Воспроизведение исходного байта [] без отправки через SoundTouch просто приводит к небольшому щелчку, где заголовок.

После отправки по конвейеру SoundTouch я воспроизвожу белый шум, где должно начинаться начало звука. Я предполагаю, что у меня возникла проблема в конце моей функции write(), где я накладываю короткие буквы на подписанные символы. Здесь, приложение консоли запись в файл, вместо того, толкая к вектору:

int res = (int)fwrite(temp, 1, numBytes, fptr); 

Я прочитал документацию для fwrite, но я не знаю достаточно о с битами или обработки звука, чтобы знать, что делать не знаю здесь, чтобы правильно получить эту информацию в char [] вместо записи в файл. Я знаю, что теряю информацию с актерским составом, но я не уверен, как ее исправить.

В случае, если кто имеет дополнительный мотивированы, источник SoundStretch можно найти здесь: http://www.surina.net/soundtouch/sourcecode.html

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; 
} 

процесс():

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); 
} 

записи():

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; 
} 
+0

Здравствуйте! Вау. Вы писали рабочий проект с SoundTouch? Респект! Не могли бы вы поделиться некоторым тестовым проектом (установить данные pcm (байты или шорты), сдвиг высоты тона и получить обратно данные для воспроизведения в AudioTrack) [email protected] TY! –

ответ

0

I просто необходимо получить все биты в char []:

for (int i = 0; i < numElems; ++i) 
{ 
    bufferOut.push_back(temp[i] & 0xff); 
    bufferOut.push_back((temp[i] >> 8) & 0xff); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^