iOS:Pitch Shifting & Piping 从 OpenAL 输出到缓冲区

Posted

技术标签:

【中文标题】iOS:Pitch Shifting & Piping 从 OpenAL 输出到缓冲区【英文标题】:iOS: Pitch Shifting & Piping output from OpenAL into a buffer 【发布时间】:2010-12-06 09:29:01 【问题描述】:

我最近发现在 ios 中可以使用 OpenAL 进行音高转换。

我在看 Hollance 的声音库播放器。它接收分布在整个范围内的 15 个左右的钢琴音符,并通过确定它最接近哪个样本来播放任何音符,并将该样本的音高移动适当的量。这是执行此操作的代码:

- (void) noteOn: (int) midiNoteNumber 
           gain: (float) gain

    if (!initialized)
    
        NSLog(@"SoundBankPlayer is not initialized yet");
        return;
    

    int sourceIndex = [self findAvailableSource];
    if (sourceIndex != -1)
    
        alGetError();  // clear any errors

        Note* note = notes + midiNoteNumber;
        if (note->bufferIndex != -1)
        
            Buffer* buffer = buffers + note->bufferIndex;
            Source* source = sources + sourceIndex;

            source->noteIndex = midiNoteNumber;

            alSourcef(source->sourceId, AL_PITCH, note->pitch / buffer->pitch);
            alSourcei(source->sourceId, AL_LOOPING, AL_FALSE);
            alSourcef(source->sourceId, AL_REFERENCE_DISTANCE, 100.0f);
            alSourcef(source->sourceId, AL_GAIN, gain);

            float sourcePos[] =  note->panning, 0.0f, 0.0f ;
            alSourcefv(source->sourceId, AL_POSITION, sourcePos);

            alSourcei(source->sourceId, AL_BUFFER, AL_NONE);
            alSourcei(source->sourceId, AL_BUFFER, buffer->bufferId);
            ALenum error;
            if ((error = alGetError()) != AL_NO_ERROR)
            
                NSLog(@"Error attaching buffer to source: %x", error);
                return;
            

            alSourcePlay(source->sourceId);
            if ((error = alGetError()) != AL_NO_ERROR)
            
                NSLog(@"Error starting source: %x", error);
                return;
            
        
    

你可以看到这条线做了音高变换:

        alSourcef(source->sourceId, AL_PITCH, note->pitch / buffer->pitch);

不幸的是,这不适合同时演奏一捆音符,因为这会占用过多的 CPU。它是动态变化的。

我想要为每个钢琴音符创建一个缓冲区,并使用这种音高转换技术填充这些缓冲区。但我看不到如何让 openAL 将声音播放到缓冲区中,而不是通过扬声器播放出来。

有什么方法可以通过管道输出 alSourcePlay(source->sourceId);

进入缓冲区?

如果我不能这样做,我有什么选择?我曾尝试使用 DSPDimension 文章中的 smbPitchShift,但它并没有提供良好的保真度:钢琴音符的起音阶段确实丢失了。我想我可以使用免费版的 Dirac3...(我目前没有钱购买完整版,但我认为免费版允许单声道处理,所以我可以破解它)。还有其他选择吗?

编辑:我已经测试了 Dirac3,它也有同样的问题。它似乎包围了攻击。似乎 OpenAL 的音高转换器以某种方式做了 Dirac3 没有做的事情。

【问题讨论】:

我喜欢带有说明性源代码的问题!非常感谢,它对我帮助很大! :) 别忘了把它加起来;) 【参考方案1】:

alSourcePlayv 允许您同时播放多个源 - 源的最大数量取决于平台,但在 iOS 上为 32(在苹果核心音频列表中回答,此处为完整性)

【讨论】:

以上是关于iOS:Pitch Shifting & Piping 从 OpenAL 输出到缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

CF1368G Shifting Dominoes

848.Shifting Letters——weekly contest 87

CF 286B(Shifting-deque)

String Shifting

Packers And Movers Bangalore | Affordable Local Household Shifting

英文下肢结构Hip Yaw Pitch, Hip Pitch, Hip Roll, Knee Pitch, Ankle Pitch, Ankle Roll的翻译