I'm trying to make app that transmits SuperpoweredAndroidAudioIO buffer from one android device to another. With the following code I've managed to send and receive short int buffer from the audio callback. However on the receiving side sound gets very distorted during playback.
Note: For brevity I have not included some code that doesen't seem to have to do with issue, including socket initialisation related functions. If needed I can add the code.
Sending side:
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");
}
Receiving side consists of 2 parts: Mixer and Channel
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");
}
At first I thought that because AudioIO on both sided get initialised with different buffer sizes (different devices 240 and 512), but then I tried to hardcode 512 into both of them but it didn't help.
I also tried to increase buffer sizes in sendto() and recvfrom() up to 4096 and it made sound more recognizable but still too distorted.
I should also add that I'm a newbie in C++ and I stuck to 'naive' and 'whatever works' approaches which got me this far.
I want to understand whether I'm on the right track and what approach should I take in order to transmit audio without distortion.