現在、私はコンピュータサイエンスの学士号の一部としてアプリケーションを開発中です。アプリケーションは、iPhoneハードウェア(加速度計、GPS)と再生されている音楽のデータを相関させます。AVAssetReaderを使用してiOSでデコードされたPCMサンプルを正しく読み込む方法 - 現在正しくないデコード
このプロジェクトはまだ初期段階にあり、わずか2ヶ月間作業しています。
私は今、私が助けが必要な瞬間、iTunesライブラリの曲からPCMサンプルを読み込み、オーディオユニットを使って再生しています。 私が働きたいと思っている実装は以下の通りです:iTunesからランダムな曲を選択し、必要に応じてサンプルを読み込み、バッファに保存してsampleBufferを呼び出します。後でコンシューマモデルでは、オーディオユニット(ミキサーとリモートIO出力を持つ)にコールバックがあり、ここで必要な数のサンプルをsampleBufferからコールバックで指定されたバッファにコピーするだけです。私がスピーカーを通して聞いていることは、私が期待しているものではないものです。私はそれが間違ってデコードされているように見えるが、それは歌を演奏していることを認識することができ、それは多くのノイズを持っています!私は最初の1/2秒(24576サンプル、44.1kHz)を示す画像を添付しました。これはノーマルな見た目の出力に似ていません。 リストに入る前に、ファイルが壊れていないことを確認しました。同様に、バッファのテストケースを書きました(バッファがサンプルを変更しないことを知っています)。これは最善の方法ではないかもしれませんそれは(オーディオキューのルートに行くと主張する人もいます)、サンプルのさまざまな操作を行い、終了する前に曲を変更したり、再生されている曲を並べ替えるなどしたいと思います。しかし、サンプルを表示するグラフ(サンプルが正しくデコードされていないことを示す)はバッファから直接取り出されるため、ディスクからの読み込みとデコードが正しく機能しない理由を解決するためだけに探しています。今は単に働きながら遊びたいだけです。 カントポスト像ため、その相続人は、画像へのリンクをStackOverflowのために新しい:http://i.stack.imgur.com/RHjlv.jpg
リスト:
これがどこにあるIセットアップ今AVAssetReaderAudioMixOutput
// Set the read settings
audioReadSettings = [[NSMutableDictionary alloc] init];
[audioReadSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
forKey:AVFormatIDKey];
[audioReadSettings setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
[audioReadSettings setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsNonInterleaved];
[audioReadSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
のために使用されますaudioReadSettigns次のコードリストは、曲のpersistant_idを含むNSStringを受け取るメソッドです。
-(BOOL)setNextSongID:(NSString*)persistand_id {
assert(persistand_id != nil);
MPMediaItem *song = [self getMediaItemForPersistantID:persistand_id];
NSURL *assetUrl = [song valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetUrl
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
NSError *assetError = nil;
assetReader = [[AVAssetReader assetReaderWithAsset:songAsset error:&assetError] retain];
if (assetError) {
NSLog(@"error: %@", assetError);
return NO;
}
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, songAsset.duration);
[assetReader setTimeRange:timeRange];
track = [[songAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
assetReaderOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:[NSArray arrayWithObject:track]
audioSettings:audioReadSettings];
if (![assetReader canAddOutput:assetReaderOutput]) {
NSLog(@"cant add reader output... die!");
return NO;
}
[assetReader addOutput:assetReaderOutput];
[assetReader startReading];
// just getting some basic information about the track to print
NSArray *formatDesc = ((AVAssetTrack*)[[assetReaderOutput audioTracks] objectAtIndex:0]).formatDescriptions;
for (unsigned int i = 0; i < [formatDesc count]; ++i) {
CMAudioFormatDescriptionRef item = (CMAudioFormatDescriptionRef)[formatDesc objectAtIndex:i];
const CAStreamBasicDescription *asDesc = (CAStreamBasicDescription*)CMAudioFormatDescriptionGetStreamBasicDescription(item);
if (asDesc) {
// get data
numChannels = asDesc->mChannelsPerFrame;
sampleRate = asDesc->mSampleRate;
asDesc->Print();
}
}
[self copyEnoughSamplesToBufferForLength:24000];
return YES;
}
今sampleBufferが誤って復号されたサンプルを持っています
-(void)copyEnoughSamplesToBufferForLength:(UInt32)samples_count {
[w_lock lock];
int stillToCopy = 0;
if (sampleBuffer->numSamples() < samples_count) {
stillToCopy = samples_count;
}
NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];
CMSampleBufferRef sampleBufferRef;
SInt16 *dataBuffer = (SInt16*)malloc(8192 * sizeof(SInt16));
int a = 0;
while (stillToCopy > 0) {
sampleBufferRef = [assetReaderOutput copyNextSampleBuffer];
if (!sampleBufferRef) {
// end of song or no more samples
return;
}
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBufferRef);
CMItemCount numSamplesInBuffer = CMSampleBufferGetNumSamples(sampleBufferRef);
AudioBufferList audioBufferList;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBufferRef,
NULL,
&audioBufferList,
sizeof(audioBufferList),
NULL,
NULL,
0,
&blockBuffer);
int data_length = floorf(numSamplesInBuffer * 1.0f);
int j = 0;
for (int bufferCount=0; bufferCount < audioBufferList.mNumberBuffers; bufferCount++) {
SInt16* samples = (SInt16 *)audioBufferList.mBuffers[bufferCount].mData;
for (int i=0; i < numSamplesInBuffer; i++) {
dataBuffer[j] = samples[i];
j++;
}
}
CFRelease(sampleBufferRef);
sampleBuffer->putSamples(dataBuffer, j);
stillToCopy = stillToCopy - data_length;
}
free(dataBuffer);
[w_lock unlock];
[apool release];
}
:(空)copyEnoughSamplesToBufferForLength -
次の機能を提供します。なぜこれがそうだと誰でも助けてくれますか?これは、私のiTunesライブラリ(mp3、aac、wavなど)のさまざまなファイルで発生します。 さらに、私のコードの他のリストが必要な場合、または出力がどのように聞こえる場合は、リクエストごとに添付します。私は過去1週間、これをデバッグしようとしていましたが、オンラインでヘルプを見つけられませんでした。誰もが自分のやり方でやっているようですが、私はこの問題を抱えているようです。
ありがとうございました!私は、私は、ファイルを再生するためにkAudioUnitSubType_AudioFilePlayerを使用し、ユニットとそのサンプルにアクセスしますどちらかあなただったら
ピーター
ありがとう!本当に役に立ちました! – Peter
kUnitSizeとは何ですか? kTotalBufferSizeとは何ですか? –
@smartfaceweb:私の場合、私が使用している以下の設定 'の#define kUnitSizeはsizeof(AudioSampleType) の#defineは、あなたがこのコードはで動作するかどうか私たちに知らせてくださいすることができます655360 の#define kTotalBufferSize kBufferUnit * kUnitSize' – infiniteloop