4

我最近发现在 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 没有做的事情。

4

1 回答 1

4

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

于 2010-12-07T17:08:31.353 回答