Android — SuperpoweredAndroidAudioIO и передача аудио через сокет UDP

Я пытаюсь сделать приложение, которое передает буфер SuperpoweredAndroidAudioIO с одного устройства Android на другое. С помощью следующего кода мне удалось отправить и получить короткий int буфер из аудио обратного вызова. Однако на принимающей стороне звук сильно искажается во время воспроизведения.

Примечание. Для краткости я не включил код, который, кажется, не имеет отношения к проблеме, включая функции, связанные с инициализацией сокетов. При необходимости я могу добавить код.

Отправляющая сторона:

Mic.cpp

static bool SendBuffer(
int sd,
sockaddr_in address,
short int *buffer,
size_t bufferSize) {

// Send data buffer to the socket
ssize_t sentSize = sendto(sd,
buffer,
bufferSize,
0,
(struct sockaddr*)&address,
sizeof address);

// If send is failed
if (sentSize == -1){
__android_log_print(ANDROID_LOG_INFO, "Sent size ", "%i error %i",
sentSize , errno);
}
else if (sentSize > 0) {
__android_log_print(ANDROID_LOG_INFO, "DatagramSent : ", "%hi size: %hi",
buffer, sentSize);
}
return true;
}

// audio callback
static bool micProcessing(
void *clientdata,
short int *audioInputOutput,
int numberOfSamples,
int __unused samplerate) {

return SendBuffer(micSocket, dsocket, audioInputOutput, numberOfSamples);

}

// Constructor
Mic::Mic(JNIEnv *env,
unsigned int samplerate,
unsigned int buffersize,
unsigned int port){

micSocket = NewUdpSocket(env);
dsocket = initDestinationSocket(port); // where to send
__android_log_write(ANDROID_LOG_DEBUG, "Sockets", "initialised");

// init IO
microphone =  new SuperpoweredAndroidAudioIO(samplerate,
buffersize,
true,
false,
micProcessing,
this,
-1,
SL_ANDROID_STREAM_MEDIA,
buffersize*2);

__android_log_write(ANDROID_LOG_DEBUG, "Mic", "initialised");
}

Приемная сторона состоит из 2 частей: Смеситель а также канал

Mixer.cpp

//audio callback
static bool mainprocess(
void *clientdata,
short int *audioInputOutput,
int numberOfSamples,
int __unused samplerate) {

return ((Mixer*)clientdata)->processMain(audioInputOutput, numberOfSamples);
}
// Setting up Mixer
Mixer::Mixer(JNIEnv *env,unsigned int samplerate, unsigned int buffersize) {
//Short int buffers for recieving
channel1 = new Channel(samplerate,buffersize);
//output buffer
outputFloat = ((float *)memalign(16, (buffersize + 16) * sizeof(float) * 2));

//volumes
outputLevel = 0.5f;

channel1level = 0.2f;
channel2level = 0.2f;
channel3level = 0.2f;
channel4level = 0.2f;

mainmixer = new SuperpoweredMonoMixer();
__android_log_print(ANDROID_LOG_INFO, "Mixer", " Created");

main = new SuperpoweredAndroidAudioIO(
samplerate,
buffersize,
false,
true,
mainprocess,
this,
-1,
SL_ANDROID_STREAM_MEDIA,
buffersize*2);

__android_log_write(ANDROID_LOG_INFO, "Main AudioIO created", " ");
main->stop();

SuperpoweredCPU::setSustainedPerformanceMode(true); // Prevents CPU drops
}
// processing.
bool Mixer::processMain(short int *outputbuffer, unsigned int numberOfSamples{
// a bit awkward
channel1->returnFloatBuffer();
inputs[0] = channel1->floatBuffer;

inputs[1] = NULL;
inputs[2] = NULL;
inputs[3] = NULL;

__android_log_print(ANDROID_LOG_INFO, "Channels are inside", " of mixer");
inputLevels[0] = channel1level;
inputLevels[1] = channel2level;
inputLevels[2] = channel3level;
inputLevels[3] = channel4level;

mainmixer->process(inputs,
outputFloat,
inputLevels,
outputLevel,
numberOfSamples);

SuperpoweredFloatToShortInt(outputFloat, outputbuffer, numberOfSamples);
return true;
}

Channel.cpp

//receiving buffer

static bool  ReceiveDatagramFromSocket(int sd, short int *buffer, size_t bufferSize) {

ssize_t  recvSize = recvfrom(sd, buffer, bufferSize, 0, NULL, NULL);

if (-1 == recvSize){ // If failed
__android_log_print(ANDROID_LOG_INFO, "receive failed", " %i  ", errno);
}
else {
// If data is received
if (recvSize > 0) {
__android_log_print(ANDROID_LOG_INFO, "Received"," %i bytes: %hi", recvSize, buffer);
}
}
return true;
}
// init channel
Channel::Channel(unsigned int samplerate, unsigned int buffersize){
socketIn = NewUdpSocket();
BindSocketToPort(socketIn);

samplerRate = samplerate;
bufferSize = buffersize;

shortIntBuffer = (short int *)malloc((buffersize + 16) * sizeof(short int)*4);
floatBuffer = (float *)memalign(16, (buffersize + 16) * sizeof(float) * 2);

bandEQ = new Superpowered3BandEQ(samplerate);
bandEQ->enable(true);
__android_log_print(ANDROID_LOG_INFO, "Channel ", "created");
}

// this function is called from Mixer.cpp
void Channel::returnFloatBuffer(){
ReceiveDatagramFromSocket(socketIn, shortIntBuffer, bufferSize);
Converting the 16-bit integer samples to 32-bit floating point.
SuperpoweredShortIntToFloat(shortIntBuffer, floatBuffer, bufferSize, 1);
bandEQ->process(floatBuffer, floatBuffer, bufferSize );
__android_log_print(ANDROID_LOG_INFO, "EQ", " processing");
}

Сначала я думал, что так как AudioIO на обеих сторонах инициализируется с разными размерами буфера (разные устройства 240 и 512), но затем я попытался жестко закодировать 512 в обоих, но это не помогло.

Я также попытался увеличить размеры буфера в sendto () и recvfrom () до 4096, и это сделало звук более узнаваемым, но все же слишком искаженным.

Я должен также добавить, что я новичок в C ++, и я придерживаюсь «Наивный» а также «что бы ни работало» подходы, которые дали мне это далеко.

Я хочу понять, нахожусь ли я на правильном пути, и какой подход я должен использовать, чтобы передавать звук без искажений.

1

Решение

У вашего подхода есть две основные проблемы:

  • Следует избегать блокирующих функций, таких как работа в сети, с помощью обратного вызова обработки звука. Вам нужно выполнить сетевое взаимодействие (с обеих сторон) из другого потока, и вам потребуется некоторая буферизация между обратным вызовом обработки аудио и сетевым потоком для передачи аудио.

  • Вам нужно «пакетировать» передачи, вам нужно обрабатывать сетевые пакеты с обеих сторон. Передача по сети не является ни быстрой, ни надежной, поэтому для этого нужны умные механизмы.

В общем, реализация для такой передачи звука намного, намного сложнее вашего текущего кода.

0

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

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

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