Воспроизведение данных PCM с использованием аудиоочередей

Я обратился к этому для воспроизведения файла PCM с использованием Аудио очереди. Код выглядит следующим образом:

#import "PlayPCM.h"
AudioFileID audioFile;
SInt64 inStartingPacket = 0;
AudioQueueRef audioQueue;

@implementation PlayPCM


void AudioOutputCallback(
                         void* inUserData,
                         AudioQueueRef outAQ,
                         AudioQueueBufferRef outBuffer)
{

    AudioStreamPacketDescription* packetDescs;

    UInt32 bytesRead;
    UInt32 numPackets = 8000;
    OSStatus status;
    status = AudioFileReadPackets(audioFile,
                                  false,
                                  &bytesRead,
                                  packetDescs,
                                  inStartingPacket,
                                  &numPackets,
                                  outBuffer->mAudioData);


    if(numPackets)
    {
        outBuffer->mAudioDataByteSize = bytesRead;
        status = AudioQueueEnqueueBuffer(audioQueue,
                                         outBuffer,
                                         0,
                                         packetDescs);

        inStartingPacket += numPackets;
    }
    else
    {
        NSLog(@"number of packets = null ") ;
        AudioQueueFreeBuffer(audioQueue, outBuffer);
    }

}

-(id)init{
    if (self = [super init]) {

    }
    return self;
}
- (void)setupAudioFormat
{

    NSLog(@"setting format");
    format.mFormatID = kAudioFormatLinearPCM;
    format.mSampleRate = 44100;
    format.mFramesPerPacket = 1;
    format.mChannelsPerFrame = 1;
    format.mBytesPerFrame = 2;
    format.mBytesPerPacket = 2;
    format.mBitsPerChannel = 16;
    format.mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
    kLinearPCMFormatFlagIsSignedInteger |
    kLinearPCMFormatFlagIsPacked;
}

- (void)startPlayback
{

    int counter = 0;
    [self setupAudioFormat];
    OSStatus status;
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString  *filePath = [documentsDirectory stringByAppendingPathComponent:@ "test1.wav"];
    NSLog(@"file path = %@",filePath);
    //fUrl = [NSURL URLWithPath:@"file:///Users/Inscripts/Desktop/test1.wav"];
    fUrl = [NSURL fileURLWithPath:filePath];
    //CFURLRef fileURL =  (__bridge CFURLRef)(fUrl);
    CFURLRef fileURL = CFURLCreateWithString(NULL, (CFStringRef) filePath, NULL);
    status = AudioFileOpenURL(fileURL, kAudioFileReadPermission, 0,&audioFile);
    NSLog(@"file opening status = %d",(int)status);
    if(status == 0)
    {   NSLog(@"file opened");
        status = AudioQueueNewOutput(&(format),
                                     AudioOutputCallback,
                                     (__bridge void *)(self),
                                     CFRunLoopGetCurrent(),
                                     kCFRunLoopCommonModes,
                                     0,
                                     &audioQueue);
        NSLog(@"audio queue create status = %d",(int)status);

        if(status == 0)
        {


                AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer);
                AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer);
             [self performSelector:@selector(startQueue) withObject:self afterDelay:50];

        }
    }

    if(status != 0)
    {
        NSLog(@"failed");
        //    labelStatus.text = @"Play failed";
    }
}

-(void)startQueue{
    NSLog(@"start queue called");
    OSStatus status = AudioQueueStart(audioQueue, NULL);
    if(status == 0)
    {
        NSLog(@"ok");

        //     labelStatus.text = @"Playing";
    }
}

Файл test1.wav закодирован в формате PCM, 16 бит на выборку, частота дискретизации 44100 Гц, стерео. Я могу успешно создать аудио-очередь и прочитать файл, но все, что я слышу, это треск. Может ли кто-нибудь сказать мне, в чем проблема?


person user2955351    schedule 15.04.2014    source источник


Ответы (2)


Является ли звук действительно данными с обратным порядком байтов - я сомневаюсь, что это файлы WAVE.

Посмотрите свои флаги формата и измените их, чтобы использовать данные с прямым порядком байтов, поэтому: !kLinearPCMFormatFlagIsBigEndian

Также рассмотрите возможность использования AudioFileOpenURLor, поскольку это будет считывать фактический формат волны, и вам не нужно полагаться на описание вашего аудиопотока.

person Volker    schedule 15.04.2014
comment
что делать, если я не читаю данные ни из одного файла? Я просто проигрываю поступающие аудиоданные, в таком случае какие изменения нужно внести? - person user2955351; 15.04.2014
comment
как указано выше, измените на littleEndian; убедитесь, что данные доступны во время игры и, возможно, обнулите свои буферы перед игрой - person Volker; 15.04.2014
comment
Фактический сценарий заключается в том, что я получаю данные речи. Для декодирования этих данных speex я настроил и скомпилировал FFMPEG для декодирования speex. Но это не работает. Пожалуйста, обратитесь к этой ссылке. Поэтому я попытался использовать эту структуру, которая дает линейные данные PCM. Для первого пакета я получаю нулевые байты в качестве декодированных данных, а затем несколько полезных байтов. Я воспроизводю эти данные с помощью AudioQueues, но ничего не слышу. - person user2955351; 15.04.2014
comment
так что ошибка, возможно, не в настройке звука, а где-то посередине... я не знаю эту структуру, поэтому я понятия не имею, в чем может быть проблема при ее использовании. - person Volker; 15.04.2014
comment
Не могли бы вы уточнить? - person user2955351; 15.04.2014
comment
Ладно. Но я тоже не могу воспроизвести этот файл. Это не использует какую-либо структуру - person user2955351; 15.04.2014
comment
Можете ли вы проверить эту ссылку. Я использую тот же проект для воспроизведения файла .wav . Но все равно слышен треск. - person user2955351; 15.04.2014

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

...
/*    AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer);
      AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer);*/

/*    add more audio queue buffers, ex:3    */
int kNumberOfBuffers = 3;
AudioQueueBufferRef audioQueueBuffer[kNumberOfBuffers];
for (int i = 0; i<kNumberOfBuffers; i++) {
    AudioQueueAllocateBuffer(audioQueue, 1600000, &audioQueueBuffer[i]);
    AudioOutputCallback((__bridge void *)(self), audioQueue, audioQueueBuffer[i]);
}
[self performSelector:@selector(startQueue) withObject:self afterDelay:50];
...
person Roger    schedule 11.01.2017