Objective-C - 将流数据传递到音频队列
我目前正在iOS上开发一个应用程序,它通过TCP套接字读取IMA-ADPCM音频数据并将其转换为PCM,然后播放流。在这个阶段,我已经完成了从流中提取数据并且将其解码为PCM的类(或者我应该说是对推送作出反应)。我还设置了音频队列类并让它播放测试音。我需要帮助的地方是将数据传递到音频队列的最佳方式。Objective-C - 将流数据传递到音频队列
音频数据从ADPCM解码器输出为8Khz 16位LPCM,每个字节640个字节。 (它起源于160字节的ADPCM数据,但解压缩到640)。它作为uint_8t数组进入函数并传出一个NSData对象。该流是一个“推送”流,因此每次发送音频时都会创建/刷新对象。
-(NSData*)convertADPCM:(uint8_t[]) adpcmdata {
课程的音频队列回调是去寻找在运行每个循环过程数据的拉动作用,在每个传递运行:
-(OSStatus) fillBuffer: (AudioQueueBufferRef) buffer {
我一直工作在这几天之后,PCM的转换完全是要征税的,我头脑中有一些麻烦,是弥合两者之间数据的最佳方式。这不像我正在创建数据,那么我可以简单地将数据创建合并到fillbuffer例程中,而不是数据被推送。
我的确在uint16_t []中设置了一个0.5秒的循环缓冲区,但是我认为我已经把我的大脑磨损了,无法用一种简洁的方式从缓冲区中推拉,所以我最终与快速爆裂弹出。
我已经完成了大部分在Android上的项目,但是发现AudioTrack与Core-Audio Queues非常不同。
在这个阶段,我还会说我拿起Adamson和Avila的Learning Core Audio的副本,并发现这是一个非常好的资源,可以帮助任何想要揭开核心音频的人。
UPDATE: 这里是缓冲区管理代码:
-(OSStatus) fillBuffer: (AudioQueueBufferRef) buffer {
int frame = 0;
double frameCount = bufferSize/self.streamFormat.mBytesPerFrame;
// buffersize = framecount = 8000/2 = 4000
//
// incoming buffer uint16_t[] convAudio holds 64400 bytes (big I know - 100 x 644 bytes)
// playedHead is set by the function to say where in the buffer the
// next starting point should be
if (playHead > 99) {
playHead = 0;
}
// Playstep factors playhead to get starting position
int playStep = playHead * 644;
// filling the buffer
for (frame = 0; frame < frameCount; ++frame)
// framecount = 4000
{
// pointer to buffer
SInt16 *data = (SInt16*)buffer->mAudioData;
// load data from uint16_t[] convAudio array into frame
(data)[frame] = convAudio[(frame + playStep)];
}
// set buffersize
buffer->mAudioDataByteSize = bufferSize;
// return no Error - Osstatus will return an error otherwise if there is one. (I think)
return noErr;
}
正如我所说,我的脑子是模糊的,当我写这一点,可能有一些昭然若揭我失踪。
上面的代码是由回调称为:
static void MyAQOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer)
{
soundHandler *sHandler = (__bridge soundHandler*)inUserData;
CheckError([sHandler fillBuffer: inCompleteAQBuffer],
"can't refill buffer",
"buffer refilled");
CheckError(AudioQueueEnqueueBuffer(inAQ,
inCompleteAQBuffer,
0,
NULL),
"Couldn't enqueue buffer (refill)",
"buffer enqued (refill)");
}
对事物的convAudio阵列端我都甩它来记录和它得到填补,以循环方式填充,所以我知道至少该位正在工作。
管理费率的难点在于如果不匹配,该怎么办。首先,尝试使用一个巨大的循环缓冲区(许多秒),并且在开始音频队列以从中拉出之前大部分时间填充它。然后监视缓冲区级别,以查看他有很大的速率匹配问题。
发布您的缓冲区管理代码,因为这似乎是你的问题。 – hotpaw2
已添加缓冲区代码。 – DoctorDbx