SuperPoweredAndroidaudioio和UDP插座音频传输
SuperpoweredAndroidAudioIO and UDP socket audio transmission
我正在尝试制作将SuperPoperPodeDandroidaudioio缓冲区从一个Android设备传输到另一个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个部分组成:混音器和 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");
}
起初,我认为这是因为两种方面的Audioio都用不同的缓冲尺寸(不同的设备240和512)进行初始化,但是随后我尝试将两个硬码512纳入两个方面,但这无济于事。
我还试图将sendto()和recvfrom()中的缓冲尺寸提高到4096,这使得听起来更易于识别,但仍然太扭曲了。
我还应该补充说,我是C 的新手,我坚持'naive'和'Whathing Working'P> 我想了解我是否在正确的轨道上,以及我应该采用哪种方法来传输音频而不会失真。
您的方法有两个主要问题:
-
阻止函数,例如网络,应从音频处理回调避免。您需要从另一个线程执行(两侧)网络,并且需要在音频处理回调和网络线程之间进行一些缓冲才能传递音频。
-
您需要"包装"传输,需要处理两侧的网络数据包。网络传输不是快速或可靠的,因此您需要巧妙的机制来处理此问题。
通常,此类音频传输的实现对您当前的代码要复杂得多。
相关文章:
- 用c++阅读音频
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- Angelscript从C++传输数组
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 为什么这个音频包络不能通过开关的情况?
- 从服务器传输到客户端的消息不会出现
- FFMpeg库:如何在音频文件中精确查找
- USB传输的LibUSB C++格式不同
- 需要反转音频步进公式
- 如何在音频处理中使用超能力时间拉伸类
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- 将相机数据从服务器实时流式传输到客户端
- 加密在 Windows、C++ 和 Java 中传输中的数据
- 将音频从浏览器流式传输到WebRTC本机C++应用程序
- 使用IMFSourceReader(Microsoft媒体基金会)进行音频流传输
- QTCPSocket(Qt-C++)中的音频文件逐字节传输
- 在 C++/CLR 中使用 ffmpeg 库流式传输音频,avcodec_fill_audio_frame返回 -22
- SuperPoweredAndroidaudioio和UDP插座音频传输
- 如何获取 mp3 音频数据包以在 C/C++ 中流式传输
- Live555可在一个RTSP流中流式传输实时视频和音频