Преобразование короткого [] из аудио библиотеки SoundTouch для воспроизведения

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

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

С моей текущей временной установкой я игнорирую заголовок RIFF и преобразовываю его вместе с данными .wav, потому что Java AudioTrack объект не должен читать заголовок, он просто воспроизводит сырой 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;
}

1

Решение

Мне просто нужно было получить все биты в char []:

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]