Error[8]: Undefined offset: 4, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述根据我的研究…人们继续说它是基于不匹配/错误的格式化..但我正在使用lPCM格式化输入和输出..你怎么能出错呢?我得到的结果只是噪音..(像白噪声) 我决定只粘贴我的整个代码..也许这会有所帮助: #import "AppDelegate.h"#import "ViewController.h"@implementation AppDelegate@synthesize window = 根据我的研究…人们继续说它是基于不匹配/错误的格式化..但我正在使用lPCM格式化输入和输出..你怎么能出错呢?我得到的结果只是噪音..(像白噪声)

我决定只粘贴我的整个代码..也许这会有所帮助:

#import "AppDelegate.h"#import "VIEwController.h"@implementation AppDelegate@synthesize window = _window;@synthesize vIEwController = _vIEwController;- (BOol)application:(UIApplication *)application dIDFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    // OverrIDe point for customization after application launch.    self.vIEwController = [[VIEwController alloc] initWithNibname:@"VIEwController" bundle:nil];    self.window.rootVIEwController = self.vIEwController;    [self.window makeKeyAndVisible];    // Insert code here to initialize your application    player = [[Player alloc] init];    [self setupReader];    [self setupQueue];    // initialize reader in a new thread        internalThread =[[NSThread alloc]                     initWithTarget:self                     selector:@selector(readPackets)                     object:nil];    [internalThread start];    // start the queue. this function returns immedatly and begins    // invoking the callback,as needed,asynchronously.    //Checkerror(AudioQueueStart(queue,NulL),"AudioQueueStart Failed");    // and wait    printf("Playing...\n");    do    {        CFRunLoopRunInMode(kcfRunLoopDefaultMode,0.25,false);    } while (!player.isDone /*|| gIsRunning*/);    // isDone represents the state of the Audio file enqueuing. This does not mean the    // Audio Queue is actually done playing yet. Since we have 3 half-second buffers in-flight    // run for continue to run for a short additional time so they can be processed    CFRunLoopRunInMode(kcfRunLoopDefaultMode,2,false);    // end playback    player.isDone = true;    Checkerror(AudioQueueStop(queue,TRUE),"AudioQueueStop Failed");cleanup:    AudioQueuedispose(queue,TRUE);    AudiofileClose(player.playbackfile);    return YES;}- (voID) setupReader {    NSURL *assetURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?ID=1053020204400037178"];   // from ilham's ipod    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];    // from AVAssetReader Class Reference:     // AVAssetReader is not intended for use with real-time sources,// and its performance is not guaranteed for real-time operations.    NSError * error = nil;    AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];    AVAssetTrack* track = [songAsset.tracks objectAtIndex:0];           readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track                                                              outputSettings:nil];    //    AVAssetReaderOutput* readerOutput = [[AVAssetReaderAudioMixOutput alloc] initWithAudioTracks:songAsset.tracks audioSettings:nil];    [reader addOutput:readerOutput];    [reader startReading];   }- (voID) setupQueue{    // get the audio data format from the file    // we kNow that it is PCM.. since it's converted        AudioStreamBasicDescription dataFormat;    dataFormat.mSampleRate = 44100.0;    dataFormat.mFormatID = kAudioFormatlinearPCM;    dataFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;    dataFormat.mBytesPerPacket = 4;    dataFormat.mFramesPerPacket = 1;    dataFormat.mBytesPerFrame = 4;    dataFormat.mChannelsPerFrame = 2;    dataFormat.mBitsPerChannel = 16;    // create a output (playback) queue    Checkerror(AudioQueueNewOutput(&dataFormat,// ASBD                                   MyAQOutputCallback,// Callback                                   (__brIDge voID *)self,// user data                                   NulL,// run loop                                   NulL,// run loop mode                                   0,// flags (always 0)                                   &queue),// output: reference to AudioQueue object               "AudioQueueNewOutput Failed");    // adjust buffer size to represent about a half second (0.5) of audio based on this format    CalculateBytesForTime(dataFormat,0.5,&bufferByteSize,&player->numPacketsToRead);    // check if we are dealing with a VBR file. ASBDs for VBR files always have     // mBytesPerPacket and mFramesPerPacket as 0 since they can fluctuate at any time.    // If we are dealing with a VBR file,we allocate memory to hold the packet descriptions    bool isFormatVBR = (dataFormat.mBytesPerPacket == 0 || dataFormat.mFramesPerPacket == 0);    if (isFormatVBR)        player.packetDescs = (AudioStreamPacketDescription*)malloc(sizeof(AudioStreamPacketDescription) * player.numPacketsToRead);    else        player.packetDescs = NulL; // we don't provIDe packet descriptions for constant bit rate formats (like linear PCM)    // get magic cookie from file and set on queue    MycopyEncodercookieToQueue(player.playbackfile,queue);    // allocate the buffers and prime the queue with some data before starting    player.isDone = false;    player.packetposition = 0;    int i;    for (i = 0; i < kNumberPlaybackBuffers; ++i)    {        Checkerror(AudioQueueAllocateBuffer(queue,bufferByteSize,&audioQueueBuffers[i]),"AudioQueueAllocateBuffer Failed");            // EOF (the entire file's contents fit in the buffers)        if (player.isDone)            break;    }   }-(voID)readPackets{    // initialize a mutex and condition so that we can block on buffers in use.    pthread_mutex_init(&queueBuffersMutex,NulL);    pthread_cond_init(&queueBufferReadyCondition,NulL);    state = AS_BUFFERING;    while ((sample = [readerOutput copyNextSampleBuffer])) {        audiobufferlist audiobufferlist;        CMBlockBufferRef CMBuffer = CMSampleBufferGetDataBuffer( sample );         Checkerror(CMSampleBufferGetaudiobufferlistWithRetainedBlockBuffer(                                                                           sample,NulL,&audiobufferlist,sizeof(audiobufferlist),kCMSampleBufferFlag_audiobufferlist_Assure16Bytealignment,&CMBuffer                                                                           ),"Could not read samples");        AudioBuffer audioBuffer = audiobufferlist.mBuffers[0];        UInt32 inNumberBytes = audioBuffer.mDataByteSize;        size_t incomingDataOffset = 0;        while (inNumberBytes) {            size_t bufSpaceRemaining;            bufSpaceRemaining = bufferByteSize - bytesFilled;            @synchronized(self)            {                bufSpaceRemaining = bufferByteSize - bytesFilled;                size_t copySize;                    if (bufSpaceRemaining < inNumberBytes)                {                    copySize = bufSpaceRemaining;                             }                else                 {                    copySize = inNumberBytes;                }                // copy data to the audio queue buffer                AudioQueueBufferRef fillBuf = audioQueueBuffers[fillBufferIndex];                memcpy((char*)fillBuf->mAudioData + bytesFilled,(const char*)(audioBuffer.mData + incomingDataOffset),copySize);                 // keep track of bytes filled                bytesFilled +=copySize;                incomingDataOffset +=copySize;                inNumberBytes -=copySize;                  }            // if the space remaining in the buffer is not enough for this packet,then enqueue the buffer.            if (bufSpaceRemaining < inNumberBytes + bytesFilled)            {                [self enqueueBuffer];            }        }    }}-(voID)enqueueBuffer {    @synchronized(self)    {        inuse[fillBufferIndex] = true;      // set in use flag        buffersUsed++;        // enqueue buffer        AudioQueueBufferRef fillBuf = audioQueueBuffers[fillBufferIndex];        NSLog(@"we are Now enqueing buffer %d",fillBufferIndex);        fillBuf->mAudioDataByteSize = bytesFilled;        err = AudioQueueEnqueueBuffer(queue,fillBuf,NulL);        if (err)        {            NSLog(@"Could not enqueue queue with buffer");            return;        }        if (state == AS_BUFFERING)        {            //            // Fill all the buffers before starting. This ensures that the            // AudiofileStream stays a small amount ahead of the AudioQueue to            // avoID an audio glitch playing streaming files on iPhone SDKs < 3.0            //            if (buffersUsed == kNumberPlaybackBuffers - 1)            {                err = AudioQueueStart(queue,NulL);                if (err)                {                    NSLog(@"Couldn't start queue");                    return;                }                state = AS_PLAYING;            }        }        // go to next buffer        if (++fillBufferIndex >= kNumberPlaybackBuffers) fillBufferIndex = 0;        bytesFilled = 0;        // reset bytes filled    }    // wait until next buffer is not in use    pthread_mutex_lock(&queueBuffersMutex);     while (inuse[fillBufferIndex])    {        pthread_cond_wait(&queueBufferReadyCondition,&queueBuffersMutex);    }    pthread_mutex_unlock(&queueBuffersMutex);}#pragma mark - utility functions -// generic error handler - if err is nonzero,prints error message and exits program.static voID Checkerror(Osstatus error,const char *operation){    if (error == noErr) return;    char str[20];    // see if it appears to be a 4-char-code    *(UInt32 *)(str + 1) = CFSwAPInt32HostToBig(error);    if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {        str[0] = str[5] = '\'';        str[6] = '
readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:nil];
'; } else // no,format it as an integer sprintf(str,"%d",(int)error); fprintf(stderr,"Error: %s (%s)\n",operation,str); exit(1);}// we only use time here as a guIDeline// we're really trying to get somewhere between 16K and 64K buffers,but not allocate too much if we don't need it/*voID CalculateBytesForTime(AudioStreamBasicDescription inDesc,float64 inSeconds,UInt32 *outBufferSize,UInt32 *outNumPackets){ // we need to calculate how many packets we read at a time,and how big a buffer we need. // we base this on the size of the packets in the file and an approximate duration for each buffer. // // first check to see what the max size of a packet is,if it is bigger than our default // allocation size,that needs to become larger // we don't have access to file packet size,so we just default it to maxBufferSize UInt32 maxPacketSize = 0x10000; static const int maxBufferSize = 0x10000; // limit size to 64K static const int minBufferSize = 0x4000; // limit size to 16K if (inDesc.mFramesPerPacket) { float64 numPacketsForTime = inDesc.mSampleRate / inDesc.mFramesPerPacket * inSeconds; *outBufferSize = numPacketsForTime * maxPacketSize; } else { // if frames per packet is zero,then the codec has no predictable packet == time // so we can't tailor this (we don't kNow how many Packets represent a time period // we'll just return a default buffer size *outBufferSize = maxBufferSize > maxPacketSize ? maxBufferSize : maxPacketSize; } // we're going to limit our size to our default if (*outBufferSize > maxBufferSize && *outBufferSize > maxPacketSize) *outBufferSize = maxBufferSize; else { // also make sure we're not too small - we don't want to go the disk for too small chunks if (*outBufferSize < minBufferSize) *outBufferSize = minBufferSize; } *outNumPackets = *outBufferSize / maxPacketSize;}// many encoded formats require a 'magic cookie'. if the file has a cookie we get it// and configure the queue with itstatic voID MycopyEncodercookieToQueue(AudiofileID thefile,AudioQueueRef queue ) { UInt32 propertySize; Osstatus result = AudiofileGetPropertyInfo (thefile,kAudiofilePropertyMagiccookieData,&propertySize,NulL); if (result == noErr && propertySize > 0) { Byte* magiccookie = (UInt8*)malloc(sizeof(UInt8) * propertySize); Checkerror(AudiofileGetProperty (thefile,magiccookie),"get cookie from file Failed"); Checkerror(AudioQueueSetProperty(queue,kAudioQueueProperty_Magiccookie,magiccookie,propertySize),"set cookie on queue Failed"); free(magiccookie); }}#pragma mark - audio queue -static voID MyAQOutputCallback(voID *inUserData,AudioQueueRef inAQ,AudioQueueBufferRef inCompleteAQBuffer) { AppDelegate *appDelegate = (__brIDge AppDelegate *) inUserData; [appDelegate myCallback:inUserData inAudioQueue:inAQ audioQueueBufferRef:inCompleteAQBuffer];}- (voID)myCallback:(voID *)userData inAudioQueue:(AudioQueueRef)inAQaudioQueueBufferRef:(AudioQueueBufferRef)inCompleteAQBuffer{ unsigned int bufIndex = -1; for (unsigned int i = 0; i < kNumberPlaybackBuffers; ++i) { if (inCompleteAQBuffer == audioQueueBuffers[i]) { bufIndex = i; break; } } if (bufIndex == -1) { NSLog(@"something went wrong at queue callback"); return; } // signal waiting thread that the buffer is free. pthread_mutex_lock(&queueBuffersMutex); NSLog(@"signalling that buffer %d is free",bufIndex); inuse[bufIndex] = false; buffersUsed--; pthread_cond_signal(&queueBufferReadyCondition); pthread_mutex_unlock(&queueBuffersMutex);}@end

更新:
下面btomw的answer解决了这个问题.但我想深究这一点(大多数新手开发人员喜欢我自己,甚至当他第一次开始时通常在黑暗中使用参数,格式等进行拍摄 – 请参阅here的示例 – )

我之所以提供nul作为参数的原因
     AVURLAsset * songAsset = [AVURLAsset URLAssetWithURL:assetURL options:audioReadSettings];

是因为根据documentation和反复试验,我意识到除了lPCM以外的任何格式都会被彻底拒绝.换句话说,当你使用AVAseetReader或转换时,结果总是lPCM ..所以我认为默认格式是lPCM,所以我把它留空了..但我想我错了.

这个中的奇怪部分(请纠正我,如果我错了)就像我提到的那样……假设原始文件是.mp3,我的意图是播放它(或通过网络发送数据包等)作为MP3 ..所以我提供了一个MP3 ABSD ..资产阅读器将崩溃!所以,如果我想以原始形式发送它,我只提供空?显而易见的问题是,一旦我在另一方收到它,我就无法弄清楚它有什么样的ABSD.或者我可以吗?

更新2:您可以从github下载代码​​.

解决方法 所以这就是我认为正在发生的事情,以及我认为你可以解决它的方式.

您正在从iOS设备上的ipod(音乐)库中提取预定义项目.然后,您使用资产阅读​​器来收集它的缓冲区,并在可能的情况下将这些缓冲区排入AudioQueue.

我认为你遇到的问题是,你正在将音频队列缓冲区的输入格式设置为线性脉冲编码调制(LPCM – 希望我说得对,我可能会在首字母缩略词上关闭).您传递给资产阅读器输出的输出设置为nil,这意味着您将获得一个很可能不是LPCM的输出,而是aiff或aac或mp3或者歌曲的格式,因为它存在于iOS的媒体库.但是,您可以通过传递不同的输出设置来解决这种情况.

尝试改变

[NSDictionary dictionaryWithObjectsAndKeys:                                                 [NSNumber numberWithInt:kAudioFormatlinearPCM],AVFormatIDKey,[NSNumber numberWithfloat:44100.0],AVSampleRateKey,[NSNumber numberWithInt:2],AVNumberOfChannelsKey,[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],AVChannelLayoutKey,[NSNumber numberWithInt:16],AVlinearPCMBitDepthKey,[NSNumber numberWithBool:NO],AVlinearPCMIsNonInterleaved,AVlinearPCMIsfloatKey,AVlinearPCMIsBigEndianKey,nil];output = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track audioSettings:outputSettings];

至:

AVURLAsset* uasset = [[AVURLAsset URLAssetWithURL:<#assetURL#> options:nil]retain];AVAssetTrack*track = [uasset.tracks objectAtIndex:0];CMFormatDescriptionRef formDesc = (CMFormatDescriptionRef)[[track formatDescriptions] objectAtIndex:0];const AudioStreamBasicDescription* asbdPointer = CMAudioFormatDescriptionGetStreamBasicDescription(formDesc);//because this is a pointer and not a struct we need to move the data into a struct so we can use itAudioStreamBasicDescription asbd = {0};memcpy(&asbd,asbdPointer,sizeof(asbd));    //asbd Now contains a basic description for the track

这是我的理解(根据Apple1的文档)传递nil作为输出设置参数为您提供与原始音轨相同文件类型的样本.即使您有一个LPCM文件,其他一些设置也可能会关闭,这可能会导致您的问题.至少,这将使所有读取器输出正常化,这应该使事情更容易陷入困境.

希望有所帮助!

编辑:

the reason why I provIDed nul as a parameter for AVURLAsset *songAsset
= [AVURLAsset URLAssetWithURL:assetURL options:audioReadSettings];

was because according to the documentation and trial and error,I…

AVAssetReaders做了两件事;读回磁盘上存在的音频文件(即:mp3,aac,aiff),或将音频转换为lpcm.

如果您将nil作为输出设置传递,它将按原样读回文件,在此您是正确的.我很抱歉没有提到资产读者只允许nil或LPCM.我实际上遇到了这个问题(这是在某个地方的文档,但需要一些潜水),但没有选择在这里提及它,因为当时我不介意. Sooooo …对不起?

如果您想在阅读之前了解正在阅读的轨道的AudioStreamBasicDescription(ASBD),您可以通过以下方式获取它:

[+++]

然后,您可以将asbd转换为您认为合适的任何格式的二进制数据,并通过网络传输.然后,您应该能够开始通过网络发送音频缓冲区数据,并使用您的AudioQueue成功播放.

我实际上有一个像这样的系统不久前工作,但由于当iOS客户端设备进入后台时我无法保持连接,我无法将其用于我的目的.尽管如此,如果所有这些工作让我帮助其他可以实际使用这些信息的人,那对我来说似乎是一场胜利.

总结

以上是内存溢出为你收集整理的ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码全部内容,希望文章能够帮你解决ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码_app_内存溢出

ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码

ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码,第1张

概述根据我的研究…人们继续说它是基于不匹配/错误的格式化..但我正在使用lPCM格式化输入和输出..你怎么能出错呢?我得到的结果只是噪音..(像白噪声) 我决定只粘贴我的整个代码..也许这会有所帮助: #import "AppDelegate.h"#import "ViewController.h"@implementation AppDelegate@synthesize window = 根据我的研究…人们继续说它是基于不匹配/错误的格式化..但我正在使用lPCM格式化输入和输出..你怎么能出错呢?我得到的结果只是噪音..(像白噪声)

我决定只粘贴我的整个代码..也许这会有所帮助:

#import "AppDelegate.h"#import "VIEwController.h"@implementation AppDelegate@synthesize window = _window;@synthesize vIEwController = _vIEwController;- (BOol)application:(UIApplication *)application dIDFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    // OverrIDe point for customization after application launch.    self.vIEwController = [[VIEwController alloc] initWithNibname:@"VIEwController" bundle:nil];    self.window.rootVIEwController = self.vIEwController;    [self.window makeKeyAndVisible];    // Insert code here to initialize your application    player = [[Player alloc] init];    [self setupReader];    [self setupQueue];    // initialize reader in a new thread        internalThread =[[NSThread alloc]                     initWithTarget:self                     selector:@selector(readPackets)                     object:nil];    [internalThread start];    // start the queue. this function returns immedatly and begins    // invoking the callback,as needed,asynchronously.    //Checkerror(AudioQueueStart(queue,NulL),"AudioQueueStart Failed");    // and wait    printf("Playing...\n");    do    {        CFRunLoopRunInMode(kcfRunLoopDefaultMode,0.25,false);    } while (!player.isDone /*|| gIsRunning*/);    // isDone represents the state of the Audio file enqueuing. This does not mean the    // Audio Queue is actually done playing yet. Since we have 3 half-second buffers in-flight    // run for continue to run for a short additional time so they can be processed    CFRunLoopRunInMode(kcfRunLoopDefaultMode,2,false);    // end playback    player.isDone = true;    Checkerror(AudioQueueStop(queue,TRUE),"AudioQueueStop Failed");cleanup:    AudioQueuedispose(queue,TRUE);    AudiofileClose(player.playbackfile);    return YES;}- (voID) setupReader {    NSURL *assetURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?ID=1053020204400037178"];   // from ilham's ipod    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];    // from AVAssetReader Class Reference:     // AVAssetReader is not intended for use with real-time sources,// and its performance is not guaranteed for real-time operations.    NSError * error = nil;    AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];    AVAssetTrack* track = [songAsset.tracks objectAtIndex:0];           readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track                                                              outputSettings:nil];    //    AVAssetReaderOutput* readerOutput = [[AVAssetReaderAudioMixOutput alloc] initWithAudioTracks:songAsset.tracks audioSettings:nil];    [reader addOutput:readerOutput];    [reader startReading];   }- (voID) setupQueue{    // get the audio data format from the file    // we kNow that it is PCM.. since it's converted        AudioStreamBasicDescription dataFormat;    dataFormat.mSampleRate = 44100.0;    dataFormat.mFormatID = kAudioFormatlinearPCM;    dataFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;    dataFormat.mBytesPerPacket = 4;    dataFormat.mFramesPerPacket = 1;    dataFormat.mBytesPerFrame = 4;    dataFormat.mChannelsPerFrame = 2;    dataFormat.mBitsPerChannel = 16;    // create a output (playback) queue    Checkerror(AudioQueueNewOutput(&dataFormat,// ASBD                                   MyAQOutputCallback,// Callback                                   (__brIDge voID *)self,// user data                                   NulL,// run loop                                   NulL,// run loop mode                                   0,// flags (always 0)                                   &queue),// output: reference to AudioQueue object               "AudioQueueNewOutput Failed");    // adjust buffer size to represent about a half second (0.5) of audio based on this format    CalculateBytesForTime(dataFormat,0.5,&bufferByteSize,&player->numPacketsToRead);    // check if we are dealing with a VBR file. ASBDs for VBR files always have     // mBytesPerPacket and mFramesPerPacket as 0 since they can fluctuate at any time.    // If we are dealing with a VBR file,we allocate memory to hold the packet descriptions    bool isFormatVBR = (dataFormat.mBytesPerPacket == 0 || dataFormat.mFramesPerPacket == 0);    if (isFormatVBR)        player.packetDescs = (AudioStreamPacketDescription*)malloc(sizeof(AudioStreamPacketDescription) * player.numPacketsToRead);    else        player.packetDescs = NulL; // we don't provIDe packet descriptions for constant bit rate formats (like linear PCM)    // get magic cookie from file and set on queue    MycopyEncodercookieToQueue(player.playbackfile,queue);    // allocate the buffers and prime the queue with some data before starting    player.isDone = false;    player.packetposition = 0;    int i;    for (i = 0; i < kNumberPlaybackBuffers; ++i)    {        Checkerror(AudioQueueAllocateBuffer(queue,bufferByteSize,&audioQueueBuffers[i]),"AudioQueueAllocateBuffer Failed");            // EOF (the entire file's contents fit in the buffers)        if (player.isDone)            break;    }   }-(voID)readPackets{    // initialize a mutex and condition so that we can block on buffers in use.    pthread_mutex_init(&queueBuffersMutex,NulL);    pthread_cond_init(&queueBufferReadyCondition,NulL);    state = AS_BUFFERING;    while ((sample = [readerOutput copyNextSampleBuffer])) {        audiobufferlist audiobufferlist;        CMBlockBufferRef CMBuffer = CMSampleBufferGetDataBuffer( sample );         Checkerror(CMSampleBufferGetaudiobufferlistWithRetainedBlockBuffer(                                                                           sample,NulL,&audiobufferlist,sizeof(audiobufferlist),kCMSampleBufferFlag_audiobufferlist_Assure16Bytealignment,&CMBuffer                                                                           ),"Could not read samples");        AudioBuffer audioBuffer = audiobufferlist.mBuffers[0];        UInt32 inNumberBytes = audioBuffer.mDataByteSize;        size_t incomingDataOffset = 0;        while (inNumberBytes) {            size_t bufSpaceRemaining;            bufSpaceRemaining = bufferByteSize - bytesFilled;            @synchronized(self)            {                bufSpaceRemaining = bufferByteSize - bytesFilled;                size_t copySize;                    if (bufSpaceRemaining < inNumberBytes)                {                    copySize = bufSpaceRemaining;                             }                else                 {                    copySize = inNumberBytes;                }                // copy data to the audio queue buffer                AudioQueueBufferRef fillBuf = audioQueueBuffers[fillBufferIndex];                memcpy((char*)fillBuf->mAudioData + bytesFilled,(const char*)(audioBuffer.mData + incomingDataOffset),copySize);                 // keep track of bytes filled                bytesFilled +=copySize;                incomingDataOffset +=copySize;                inNumberBytes -=copySize;                  }            // if the space remaining in the buffer is not enough for this packet,then enqueue the buffer.            if (bufSpaceRemaining < inNumberBytes + bytesFilled)            {                [self enqueueBuffer];            }        }    }}-(voID)enqueueBuffer {    @synchronized(self)    {        inuse[fillBufferIndex] = true;      // set in use flag        buffersUsed++;        // enqueue buffer        AudioQueueBufferRef fillBuf = audioQueueBuffers[fillBufferIndex];        NSLog(@"we are Now enqueing buffer %d",fillBufferIndex);        fillBuf->mAudioDataByteSize = bytesFilled;        err = AudioQueueEnqueueBuffer(queue,fillBuf,NulL);        if (err)        {            NSLog(@"Could not enqueue queue with buffer");            return;        }        if (state == AS_BUFFERING)        {            //            // Fill all the buffers before starting. This ensures that the            // AudiofileStream stays a small amount ahead of the AudioQueue to            // avoID an audio glitch playing streaming files on iPhone SDKs < 3.0            //            if (buffersUsed == kNumberPlaybackBuffers - 1)            {                err = AudioQueueStart(queue,NulL);                if (err)                {                    NSLog(@"Couldn't start queue");                    return;                }                state = AS_PLAYING;            }        }        // go to next buffer        if (++fillBufferIndex >= kNumberPlaybackBuffers) fillBufferIndex = 0;        bytesFilled = 0;        // reset bytes filled    }    // wait until next buffer is not in use    pthread_mutex_lock(&queueBuffersMutex);     while (inuse[fillBufferIndex])    {        pthread_cond_wait(&queueBufferReadyCondition,&queueBuffersMutex);    }    pthread_mutex_unlock(&queueBuffersMutex);}#pragma mark - utility functions -// generic error handler - if err is nonzero,prints error message and exits program.static voID Checkerror(Osstatus error,const char *operation){    if (error == noErr) return;    char str[20];    // see if it appears to be a 4-char-code    *(UInt32 *)(str + 1) = CFSwAPInt32HostToBig(error);    if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {        str[0] = str[5] = '\'';        str[6] = '
readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:nil];
'; } else // no,format it as an integer sprintf(str,"%d",(int)error); fprintf(stderr,"Error: %s (%s)\n",operation,str); exit(1);}// we only use time here as a guIDeline// we're really trying to get somewhere between 16K and 64K buffers,but not allocate too much if we don't need it/*voID CalculateBytesForTime(AudioStreamBasicDescription inDesc,float64 inSeconds,UInt32 *outBufferSize,UInt32 *outNumPackets){ // we need to calculate how many packets we read at a time,and how big a buffer we need. // we base this on the size of the packets in the file and an approximate duration for each buffer. // // first check to see what the max size of a packet is,if it is bigger than our default // allocation size,that needs to become larger // we don't have access to file packet size,so we just default it to maxBufferSize UInt32 maxPacketSize = 0x10000; static const int maxBufferSize = 0x10000; // limit size to 64K static const int minBufferSize = 0x4000; // limit size to 16K if (inDesc.mFramesPerPacket) { float64 numPacketsForTime = inDesc.mSampleRate / inDesc.mFramesPerPacket * inSeconds; *outBufferSize = numPacketsForTime * maxPacketSize; } else { // if frames per packet is zero,then the codec has no predictable packet == time // so we can't tailor this (we don't kNow how many Packets represent a time period // we'll just return a default buffer size *outBufferSize = maxBufferSize > maxPacketSize ? maxBufferSize : maxPacketSize; } // we're going to limit our size to our default if (*outBufferSize > maxBufferSize && *outBufferSize > maxPacketSize) *outBufferSize = maxBufferSize; else { // also make sure we're not too small - we don't want to go the disk for too small chunks if (*outBufferSize < minBufferSize) *outBufferSize = minBufferSize; } *outNumPackets = *outBufferSize / maxPacketSize;}// many encoded formats require a 'magic cookie'. if the file has a cookie we get it// and configure the queue with itstatic voID MycopyEncodercookieToQueue(AudiofileID thefile,AudioQueueRef queue ) { UInt32 propertySize; Osstatus result = AudiofileGetPropertyInfo (thefile,kAudiofilePropertyMagiccookieData,&propertySize,NulL); if (result == noErr && propertySize > 0) { Byte* magiccookie = (UInt8*)malloc(sizeof(UInt8) * propertySize); Checkerror(AudiofileGetProperty (thefile,magiccookie),"get cookie from file Failed"); Checkerror(AudioQueueSetProperty(queue,kAudioQueueProperty_Magiccookie,magiccookie,propertySize),"set cookie on queue Failed"); free(magiccookie); }}#pragma mark - audio queue -static voID MyAQOutputCallback(voID *inUserData,AudioQueueRef inAQ,AudioQueueBufferRef inCompleteAQBuffer) { AppDelegate *appDelegate = (__brIDge AppDelegate *) inUserData; [appDelegate myCallback:inUserData inAudioQueue:inAQ audioQueueBufferRef:inCompleteAQBuffer];}- (voID)myCallback:(voID *)userData inAudioQueue:(AudioQueueRef)inAQaudioQueueBufferRef:(AudioQueueBufferRef)inCompleteAQBuffer{ unsigned int bufIndex = -1; for (unsigned int i = 0; i < kNumberPlaybackBuffers; ++i) { if (inCompleteAQBuffer == audioQueueBuffers[i]) { bufIndex = i; break; } } if (bufIndex == -1) { NSLog(@"something went wrong at queue callback"); return; } // signal waiting thread that the buffer is free. pthread_mutex_lock(&queueBuffersMutex); NSLog(@"signalling that buffer %d is free",bufIndex); inuse[bufIndex] = false; buffersUsed--; pthread_cond_signal(&queueBufferReadyCondition); pthread_mutex_unlock(&queueBuffersMutex);}@end

更新:
下面btomw的answer解决了这个问题.但我想深究这一点(大多数新手开发人员喜欢我自己,甚至当他第一次开始时通常在黑暗中使用参数,格式等进行拍摄 – 请参阅here的示例 – )

我之所以提供nul作为参数的原因
     AVURLAsset * songAsset = [AVURLAsset URLAssetWithURL:assetURL options:audioReadSettings];

是因为根据documentation和反复试验,我意识到除了lPCM以外的任何格式都会被彻底拒绝.换句话说,当你使用AVAseetReader或转换时,结果总是lPCM ..所以我认为默认格式是lPCM,所以我把它留空了..但我想我错了.

这个中的奇怪部分(请纠正我,如果我错了)就像我提到的那样……假设原始文件是.mp3,我的意图是播放它(或通过网络发送数据包等)作为MP3 ..所以我提供了一个MP3 ABSD ..资产阅读器将崩溃!所以,如果我想以原始形式发送它,我只提供空?显而易见的问题是,一旦我在另一方收到它,我就无法弄清楚它有什么样的ABSD.或者我可以吗?

更新2:您可以从github下载代码​​.

解决方法 所以这就是我认为正在发生的事情,以及我认为你可以解决它的方式.

您正在从iOS设备上的ipod(音乐)库中提取预定义项目.然后,您使用资产阅读​​器来收集它的缓冲区,并在可能的情况下将这些缓冲区排入AudioQueue.

我认为你遇到的问题是,你正在将音频队列缓冲区的输入格式设置为线性脉冲编码调制(LPCM – 希望我说得对,我可能会在首字母缩略词上关闭).您传递给资产阅读器输出的输出设置为nil,这意味着您将获得一个很可能不是LPCM的输出,而是aiff或aac或mp3或者歌曲的格式,因为它存在于iOS的媒体库.但是,您可以通过传递不同的输出设置来解决这种情况.

尝试改变

[NSDictionary dictionaryWithObjectsAndKeys:                                                 [NSNumber numberWithInt:kAudioFormatlinearPCM],AVFormatIDKey,[NSNumber numberWithfloat:44100.0],AVSampleRateKey,[NSNumber numberWithInt:2],AVNumberOfChannelsKey,[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],AVChannelLayoutKey,[NSNumber numberWithInt:16],AVlinearPCMBitDepthKey,[NSNumber numberWithBool:NO],AVlinearPCMIsNonInterleaved,AVlinearPCMIsfloatKey,AVlinearPCMIsBigEndianKey,nil];output = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track audioSettings:outputSettings];

至:

AVURLAsset* uasset = [[AVURLAsset URLAssetWithURL:<#assetURL#> options:nil]retain];AVAssetTrack*track = [uasset.tracks objectAtIndex:0];CMFormatDescriptionRef formDesc = (CMFormatDescriptionRef)[[track formatDescriptions] objectAtIndex:0];const AudioStreamBasicDescription* asbdPointer = CMAudioFormatDescriptionGetStreamBasicDescription(formDesc);//because this is a pointer and not a struct we need to move the data into a struct so we can use itAudioStreamBasicDescription asbd = {0};memcpy(&asbd,asbdPointer,sizeof(asbd));    //asbd Now contains a basic description for the track

这是我的理解(根据Apple1的文档)传递nil作为输出设置参数为您提供与原始音轨相同文件类型的样本.即使您有一个LPCM文件,其他一些设置也可能会关闭,这可能会导致您的问题.至少,这将使所有读取器输出正常化,这应该使事情更容易陷入困境.

希望有所帮助!

编辑:

the reason why I provIDed nul as a parameter for AVURLAsset *songAsset
= [AVURLAsset URLAssetWithURL:assetURL options:audioReadSettings];

was because according to the documentation and trial and error,I…

AVAssetReaders做了两件事;读回磁盘上存在的音频文件(即:mp3,aac,aiff),或将音频转换为lpcm.

如果您将nil作为输出设置传递,它将按原样读回文件,在此您是正确的.我很抱歉没有提到资产读者只允许nil或LPCM.我实际上遇到了这个问题(这是在某个地方的文档,但需要一些潜水),但没有选择在这里提及它,因为当时我不介意. Sooooo …对不起?

如果您想在阅读之前了解正在阅读的轨道的AudioStreamBasicDescription(ASBD),您可以通过以下方式获取它:

然后,您可以将asbd转换为您认为合适的任何格式的二进制数据,并通过网络传输.然后,您应该能够开始通过网络发送音频缓冲区数据,并使用您的AudioQueue成功播放.

我实际上有一个像这样的系统不久前工作,但由于当iOS客户端设备进入后台时我无法保持连接,我无法将其用于我的目的.尽管如此,如果所有这些工作让我帮助其他可以实际使用这些信息的人,那对我来说似乎是一场胜利.

总结

以上是内存溢出为你收集整理的ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码全部内容,希望文章能够帮你解决ios – 当AVAssetReader与音频队列一起使用时,为什么音频会出现乱码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1053392.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存