我正在構建一款iPhone應用程序,通過以「caf」格式回放各個錄製的吉他音符來生成隨機吉他音樂。這些音符的持續時間從3秒到11秒不等,具體取決於延音量。在音頻應用程序中使用Novocaine
我最初使用AVAudioPlayer進行播放,在模擬器中以120bpm的速度播放第16個音符,但是在我的手機上,只要我的 將速度提高了60 bpm,只播放了1/4筆記,它像狗一樣跑,並不會及時。我的歡樂時光非常短暫。
爲了減少延遲,我嘗試使用Apple MixerHost項目作爲音頻引擎的模板來實現通過音頻單元進行回放,但是在我將其栓上並連接好之後,仍然出現訪問錯誤。
經過幾個小時的努力,我放棄了這種思維方式,而是放棄了Novocaine音頻引擎。
我現在碰到了一堵磚牆,試圖連接到我的模型。
在最基本的層面上,我的模型是一個包含Note對象的NSDictionary的Neck對象。
每個Note對象都知道它所在的吉他脖子上的字符串和音品,並且包含它自己的AVAudioPlayer。
根據用戶偏好中選擇的脖子尺寸,我製作了一個包含122個音符(22根22根6根弦)或144根音符(6根24根24根弦)的吉他琴頸。
我使用這些Notes作爲我的單一事實點,因此音樂引擎生成的所有標量音符都是指向此彩色音符存儲桶的指針。
@interface Note : NSObject <NSCopying>
{
NSString *name;
AVAudioPlayer *soundFilePlayer;
int stringNumber;
int fretNumber;
}
我總是開始播放與所選規模的根音符或和絃,然後生成音符播放下,所以我總是打產生的音符背後的一個音符。通過這種方式,下一個要播放的音符總是排隊準備就緒。這些票據
播放控制是一個用下面的代碼實現:
- (void)runMusicGenerator:(NSNumber *)counter
{
if (self.isRunning) {
Note *NoteToPlay;
// pulseRate is the time interval between beats
// staticNoteLength = 1/4 notes, 1/8th notes, 16th notes, etc.
float delay = self.pulseRate/[self grabStaticNoteLength];
// user setting to play single, double or triplet notes.
if (self.beatCounter == CONST_BEAT_COUNTER_INIT_VAL) {
NoteToPlay = [self.GuitarNeck generateNoteToPlayNext];
} else {
NoteToPlay = [self.GuitarNeck cloneNote:self.GuitarNeck.NoteToPlayNow];
}
self.GuitarNeck.NoteToPlayNow = NoteToPlay;
[self callOutNoteToPlay];
[self performSelector:@selector(runDrill:) withObject:NoteToPlay afterDelay:delay];
}
- (Note *)generateNoteToPlayNext
{
if ((self.musicPaused) || (self.musicStopped)) {
// grab the root note on the string to resume
self.NoteToPlayNow = [self grabRootNoteForString];
//reset the flags
self.musicPaused = NO;
self.musicStopped = NO;
} else {
// Set NoteRingingOut to NoteToPlayNow
self.NoteRingingOut = self.NoteToPlayNow;
// Set NoteToPlaNowy to NoteToPlayNext
self.NoteToPlayNow = self.NoteToPlayNext;
if (!self.NoteToPlayNow) {
self.NoteToPlayNow = [self grabRootNoteForString];
// now prep the note's audio player for playback
[self.NoteToPlayNow.soundFilePlayer prepareToPlay];
}
}
// Load NoteToPlayNext
self.NoteToPlayNext = [self generateRandomNote];
}
- (void)callOutNoteToPlay
{
self.GuitarNeck.NoteToPlayNow.soundFilePlayer.delegate = (id)self;
[self.GuitarNeck.NoteToPlayNow.soundFilePlayer setVolume:1.0];
[self.GuitarNeck.NoteToPlayNow.soundFilePlayer setCurrentTime:0];
[self.GuitarNeck.NoteToPlayNow.soundFilePlayer play];
}
每個音符的AVAudioPlayer如下加載:
- (AVAudioPlayer *)buildStringNotePlayer:(NSString *)nameOfNote
{
NSString *soundFileName = @"S";
soundFileName = [soundFileName stringByAppendingString:[NSString stringWithFormat:@"%d", stringNumber]];
soundFileName = [soundFileName stringByAppendingString:@"F"];
if (fretNumber < 10) {
soundFileName = [soundFileName stringByAppendingString:@"0"];
}
soundFileName = [soundFileName stringByAppendingString:[NSString stringWithFormat:@"%d", fretNumber]];
NSString *soundPath = [[NSBundle mainBundle] pathForResource:soundFileName ofType:@"caf"];
NSURL *fileURL = [NSURL fileURLWithPath:soundPath];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
return notePlayer;
}
這裏是我栽跟頭。
按照奴佛卡因Github的網頁...
播放音頻
Novocaine *audioManager = [Novocaine audioManager];
[audioManager setOutputBlock:^(float *audioToPlay, UInt32 numSamples, UInt32 numChannels) {
// All you have to do is put your audio into "audioToPlay".
}];
但在下載的工程,可以使用下面的代碼加載音頻...
// AUDIO FILE READING OHHH YEAHHHH
// ========================================
NSURL *inputFileURL = [[NSBundle mainBundle] URLForResource:@"TLC" withExtension:@"mp3"];
fileReader = [[AudioFileReader alloc]
initWithAudioFileURL:inputFileURL
samplingRate:audioManager.samplingRate
numChannels:audioManager.numOutputChannels];
[fileReader play];
fileReader.currentTime = 30.0;
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
[fileReader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels];
NSLog(@"Time: %f", fileReader.currentTime);
}];
這裏是我真正開始感到困惑的地方,因爲第一個方法使用了一個float,而第二個方法使用了一個URL。
如何將「caf」文件傳遞給float?我不知道如何實施諾沃卡因 - 這在我的腦海中仍然很模糊。
我的問題,我希望有人能幫助我的如下...
是奴佛卡因對象類似AVAudioPlayer對象,只是更加靈活和調整,以最大最小延遲?即自含音頻播放(/記錄/生成)單元?
我可以在我的模型中使用Novocaine嗎?即每個彩色音符有1個Novocaine對象,還是應該有1個包含所有彩色音符的novocain對象?或者我只是將該URL存儲在筆記中,然後將其傳遞給一個Novocaine玩家?
當我的音頻是「caf」文件和「audioToPlay」採取浮動時,如何將音頻放入「audioToPlay」?
如果我在Note.m中包含並聲明瞭一個Novocaine屬性,那麼我是否必須將該類重命名爲Note.mm才能使用該Novocaine對象?
如何同時播放多個Novocaine對象以重現和絃和音程?
我可以循環播放一個Novocaine對象嗎?
我可以設置音符的播放長度嗎?即僅播放10秒鐘的音符1秒?
我可以修改上面的代碼來使用Novocaine嗎?
我爲runMusicGenerator使用的方法是否正確使用以保持符合專業標準的節奏?