2

現在、AVAssetReader からサンプルを取得して、iOS で AudioQueue を使用して再生できるかどうかを確認するための小さなテスト プロジェクトを行っています。

私はこれを読みました:(AudioQueueで未加工の非圧縮サウンドを再生します、音はありません)およびこれ:(AVAssetReaderを使用してiOSでデコードされたPCMサンプルを正しく読み取る方法-現在は正しくないデコード)、

どちらも実際に役に立ちました。読む前は、まったく音が出ませんでした。今、私は音を出していますが、オーディオは超高速で再生されています. これはオーディオ プログラミングへの私の最初の進出なので、どんな助けも大歓迎です。

このようにリーダーを初期化します。

NSDictionary * outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                         [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                         [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                         [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                         [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,

                                         nil];

        output = [[AVAssetReaderAudioMixOutput alloc] initWithAudioTracks:uasset.tracks audioSettings:outputSettings];
        [reader addOutput:output];
...

そして、次のようにデータを取得します。

CMSampleBufferRef ref= [output copyNextSampleBuffer];
    // NSLog(@"%@",ref);
    if(ref==NULL)
        return;
    //copy data to file
    //read next one
    AudioBufferList audioBufferList;
    NSMutableData *data = [NSMutableData data];
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);
    // NSLog(@"%@",blockBuffer);

    if(blockBuffer==NULL)
    {
        [data release];
        return;
    }
    if(&audioBufferList==NULL)
    {
        [data release];
        return;
    }

    //stash data in same object
    for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
    {
//        NSData* throwData;
        AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
        [self.delegate streamer:self didGetAudioBuffer:audioBuffer];
        /*
        Float32 *frame = (Float32*)audioBuffer.mData;
        throwData = [NSData dataWithBytes:audioBuffer.mData length:audioBuffer.mDataByteSize];
        [self.delegate streamer:self didGetAudioBuffer:throwData];
        [data appendBytes:audioBuffer.mData length:audioBuffer.mDataByteSize];
         */
    }

最終的に、次のように設定された Audio Queue に移動します。

//Apple's own code for canonical PCM
    audioDesc.mSampleRate       = 44100.0;
    audioDesc.mFormatID         = kAudioFormatLinearPCM;
    audioDesc.mFormatFlags      = kAudioFormatFlagsAudioUnitCanonical;
    audioDesc.mBytesPerPacket   = 2 * sizeof (AudioUnitSampleType);    // 8
    audioDesc.mFramesPerPacket  = 1;
    audioDesc.mBytesPerFrame    = 1 * sizeof (AudioUnitSampleType);    // 8
    audioDesc.mChannelsPerFrame = 2;
    audioDesc.mBitsPerChannel   = 8 * sizeof (AudioUnitSampleType);    // 32


err = AudioQueueNewOutput(&audioDesc, handler_OSStreamingAudio_queueOutput, self, NULL, NULL, 0, &audioQueue);
    if(err){
#pragma warning  handle error
//never errs, am using breakpoint to check
        return;
    }

したがって、キューに入れます

while (inNumberBytes)
        {
            size_t bufSpaceRemaining = kAQDefaultBufSize - bytesFilled;
            if (bufSpaceRemaining < inNumberBytes)
            {
                AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex];
        fillBuf->mAudioDataByteSize = bytesFilled;
        err = AudioQueueEnqueueBuffer(audioQueue, fillBuf, 0, NULL);
            }


                bufSpaceRemaining = kAQDefaultBufSize - bytesFilled;
                size_t copySize;
                if (bufSpaceRemaining < inNumberBytes)
                {
                    copySize = bufSpaceRemaining;
                }
                else
                {
                    copySize = inNumberBytes;
                }

                if (bytesFilled > packetBufferSize)
                {
                    return;
                }

                AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex];
                memcpy((char*)fillBuf->mAudioData + bytesFilled, (const char*)(inInputData + offset), copySize);


                bytesFilled += copySize;
                packetsFilled = 0;
                inNumberBytes -= copySize;
                offset += copySize;
            }
        }

誰でも簡単に私がバカなところを指摘できるように、できるだけコードを含めるようにしました。そうは言っても、トラック リーダーの出力設定宣言または AudioQueue の実際の宣言 (送信するオーディオの種類をキューに記述する場所) のいずれかで問題が発生していると感じています。実際のところ、これらの数値 (パケットあたりのバイト数、パケットあたりのフレーム数、何を持っているか) を実際に生成する方法を数学的にはよく知りません。その説明は大歓迎です。事前に助けてくれてありがとう。

4

2 に答える 2

2

これがどれだけの答えかはわかりませんが、コメントにはテキストとリンクが多すぎるので、うまくいけば役に立ちます(おそらくあなたの答えに導くでしょう)。

まず、現在のプロジェクトでサンプルレートを調整すると音の速度に影響することがわかっているので、それらの設定で試してみることができます。しかし、アップルの例SpeakHereを含むほとんどのデフォルト実装で見られるのは 44k です。ただし、かなりの数の違いがあるため、コードをその例と比較するのに少し時間を費やします。キューに入れる前のチェックのように。

最初にこの投稿をチェックしてください https://stackoverflow.com/a/4299665/530933 オーディオ形式、具体的にはフレーム内のバイト数、および適切なキャストを知る必要がある方法について説明しています

幸運も。ここ、Apple フォーラム、および ios フォーラム (公式フォーラムではありません) にかなりの数の質問が投稿されました。応答/ヘルプがほとんどありません。私が今日どこにいるのか (オーディオ録音と ulaw でのストリーミング) を取得するには、Apple Dev Support チケットを開く必要がありました。オーディオに取り組む前は、存在を知らなかった (開発サポート)。1 つの良い点は、有効な開発者アカウントを持っている場合、2 つのインシデントを無料で取得できることです! CoreAudio は楽しくありません。ドキュメントはまばらで、SpeakHere 以外に多くの例はありません。私が見つけた 1 つのことは、フレームワークのヘッダーにいくつかの良い情報とこの本があることです。残念ながら、私は本を読み始めたばかりです。それ以外の場合は、さらにお手伝いできるかもしれません.

また、私ができる限り回答しようとした私自身の投稿のいくつかを確認することもできます。 これは、関連するすべてのリンクとコードをコンパイルするために多くの時間を費やしてきた私の主なオーディオの質問です。

目的の c クラスで AQRecorder (オーディオ キュー レコーダーの例) を使用する

ulaw オーディオに AVAssetWriter を使用しようとしています( 2 )

于 2012-07-09T16:34:17.747 に答える
0

何らかの理由で、LPCM を使用した Audio Queue について私が見たすべての例では、

ASBD.mBitsPerChannel = 8* sizeof (AudioUnitSampleType);

私にとっては、必要であることがわかりました

ASBD.mBitsPerChannel    = 2*bytesPerSample;

説明:

ASBD.mFormatID          = kAudioFormatLinearPCM;
ASBD.mFormatFlags       = kAudioFormatFlagsAudioUnitCanonical;
ASBD.mBytesPerPacket    = bytesPerSample;
ASBD.mBytesPerFrame     = bytesPerSample;
ASBD.mFramesPerPacket   = 1;
ASBD.mBitsPerChannel    = 2*bytesPerSample;
ASBD.mChannelsPerFrame  = 2;           
ASBD.mSampleRate        = 48000;

なぜこれがうまくいくのか、私にはよくわかりません.

なぜこれがうまくいくのか誰かが私に説明できるなら、私はとても感謝しています。

于 2012-07-10T17:29:54.663 に答える