Iphone 在音频应用程序中使用奴佛卡因
我正在构建一个iPhone应用程序,通过以“caf”格式播放单独录制的吉他音符来生成随机吉他音乐。这些音符的持续时间从3秒到11秒不等,这取决于持续的时间 我最初使用AVAudioPlayer进行播放,在模拟器中以120 bpm的速度播放16个音符,它唱得很好听,但在我的手机上,当我 将速度提高到60 bpm多一点,只播放1/4个音符,它像狗一样跑,无法跟上时间。我的兴高采烈是短暂的 为了减少延迟,我尝试使用Apple MixerHost项目作为音频引擎的模板,通过音频单元实现播放,但在我将其连接并将所有内容连接起来后,一直出现严重的访问错误 经过几个小时的努力,我放弃了思考,转而使用Novocaine音频引擎 我现在遇到一堵砖墙,试图把它和我的模型连接起来 在最基本的层面上,我的模型是一个Neck对象,其中包含一个Notes对象字典 每个音符对象都知道它所在的吉他琴颈的弦和弦,并包含自己的AVAudioPlayer 我制作了一个半音吉他琴颈,它包含122个音符(6弦22格)或144个音符(6弦24格),具体取决于用户偏好中选择的琴颈大小 我使用这些音符作为我的单一真理点,所以音乐引擎生成的所有标量音符都是指向这个彩色音符桶的指针Iphone 在音频应用程序中使用奴佛卡因,iphone,objective-c,ios,avaudioplayer,Iphone,Objective C,Ios,Avaudioplayer,我正在构建一个iPhone应用程序,通过以“caf”格式播放单独录制的吉他音符来生成随机吉他音乐。这些音符的持续时间从3秒到11秒不等,这取决于持续的时间 我最初使用AVAudioPlayer进行播放,在模拟器中以120 bpm的速度播放16个音符,它唱得很好听,但在我的手机上,当我 将速度提高到60 bpm多一点,只播放1/4个音符,它像狗一样跑,无法跟上时间。我的兴高采烈是短暂的 为了减少延迟,我尝试使用Apple MixerHost项目作为音频引擎的模板,通过音频单元实现播放,但在我将其连
@interface Note : NSObject <NSCopying>
{
NSString *name;
AVAudioPlayer *soundFilePlayer;
int stringNumber;
int fretNumber;
}
每个便笺的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;
}
但在下载的项目中,您使用以下代码加载音频
// 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);
}];
这里是我真正开始感到困惑的地方,因为第一个方法使用浮点,第二个方法使用URL
如何将“caf”文件传递给浮点?我不知道如何使用奴佛卡因,我的脑子里还不清楚
我的问题,我希望有人能帮助我如下
无需手动设置RemoteIO AudioUnit,Novocaine使您的生活更加轻松。这包括必须痛苦地填充一堆CoreAudio结构,并提供一堆回调,比如这个音频进程回调
静态OSStatus PerformThru(void*inRefCon,AudioUnitRenderActionFlags*ioActionFlags,const AudioTimeStamp*inTimeStamp,UInt32 inbunsumber,UInt32 inNumberFrames,AudioBufferList*ioData)代码>
取而代之的是,Novocaine在它的实现中处理这个问题,然后调用你的块,你可以通过这样做来设置它
[audioManager设置输出块:^(浮点*AudioTopPlay,UInt32 numSamples,UInt32 numChannel){}代码>
无论你写什么audioToPlay
都会播放
Novocaine为您设置RemoteIO AudioUnit。这是一个低级别的CoreAudio API,不同于高级别的AVFoundation,并且正如预期的那样,延迟非常低。你说得对,奴佛卡因是自给自足的。您可以实时录制、生成和处理音频
奴佛卡因是单例,不能有多个奴佛卡因实例。一种方法是将吉他声音存储在一个单独的类或数组中,然后编写一系列方法,使用Novocaine来播放它们
你有很多选择。您可以使用Novocaine的AudioFileReader为您播放.caf文件。您可以通过分配一个AudioFileReader,然后传递要播放的.caf文件的URL来实现这一点,如示例代码所示。然后在块中粘贴[fileReader retrieveFreshAudio:data numFrames:numFrames numChannels:numChannels]
,如示例代码所示。每次调用块时,AudioFileReader都会从磁盘抓取并缓冲一块音频,并将其放入audioToPlay
,然后播放。这有一些缺点。对于短音(比如我假设的吉他音),反复调用retrieveFreshAudio
是一种性能上的成功。通常最好(对于短声音)执行同步、顺序地将整个文件读入内存。奴佛卡因还没有提供一种方法来做到这一点。您必须使用ExtAudioFileServices来执行此操作。Apple示例项目MixerHost详细介绍了如何实现这一点
如果您使用的是AudioFileReader是。当您是C++时,您只重命名为.m.代码>导入/ <代码> ING,从Obj-C++标题或<代码>包含< <代码> ING C++头。< /P>
如前所述,仅允许使用1个奴佛卡因实例。您可以通过混合多个音频源来实现复调。这只是简单地将缓冲区添加到一起。如果你用不同的音高弹奏了多个版本的相同吉他声音,只要把它们都读到记忆中,
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);
}];
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels){
static int count = 0;
for(int i=0; i<numFrames; ++i){
//Mono mix each sample of each sound together. Since result can be 4x louder, divide the total amp by 4.
//You should be using `vDSP_vadd` from the accelerate framework for added performance.
data[count] = (guitarC[count] + guitarE[count] + guitarG[count] + guitarB[count]) * 0.25;
if(++count >= 44100) count = 0; //Plays the mix for 1 sec
}
}];