내가 읽은 것을 토대로 FM 사운드 합성 알고리즘을 만들었습니다. 내가 제대로했는지 확실하지 않습니다. 소프트웨어 신스 악기를 만들 때 함수는 발진기를 생성하는 데 사용되고 변조기는이 발진기의 주파수를 모듈화하는 데 사용될 수 있습니다. FM 합성이 사인파를 변조하는 데만 사용된다면 나는 모르겠다.주파수 변조 합성 알고리즘
알고리즘은 악기 파동 함수와 주파수 변조를위한 변조 지수 비율 걸린다. 각 음표에 대해 주파수를 취하고 반송파 및 변조기 오실레이터의 위상 값을 저장합니다. 변조기는 항상 사인파를 사용합니다. 음의 주파수는 100Hz로이면
가function ProduceSample(instrument, notes_playing)
for each note in notes_playing
if note.isPlaying()
# Calculate signal
if instrument.FMIndex != 0 # Apply FM
FMFrequency = note.frequency*instrument.FMRatio; # FM frequency is factor of note frequency.
note.FMPhase = note.FMPhase + FMFrequency/kGraphSampleRate # Phase of modulator.
frequencyDeviation = sin(note.FMPhase * PI)*instrument.FMIndex*FMFrequency # Frequency deviation. Max deviation is a factor of the FM frequency. Modulation is done by a sine wave.
note.phase = note.phase + (note.frequency + frequencyDeviation)/kGraphSampleRate # Adjust phase with deviation
# Reset the phase value to prevent the float from overflowing
if note.FMPhase >= 1
note.FMPhase = note.FMPhase - 1
end if
else # No FM applied
note.phase = note.phase + note.frequency/kGraphSampleRate # Adjust phase without deviation
end if
# Calculate the next sample
signal = signal + instrument.waveFunction(note.phase,instrument.waveParameter)*note.amplitude
# Reset the phase value to prevent the float from overflowing
if note.phase >= 1
note.phase = note.phase - 1
end if
end if
end loop
return signal
end function
그래서 FMRatio 0.5로 설정하고 FMIndex 그것이는 50Hz에서 95Hz와 105Hz 사이가는 주파수를 생성한다 0.1 :
이
의사 코드의 알고리즘 주기. 이것이 올바른 방법일까요? 내 테스트에 따르면 항상 톱 소리와 구형파를 조절할 때 항상 소리가 나지 않는 것으로 나타났습니다. 이런 톱과 구형파를 변조해도 괜찮습니까? 아니면 사인파 만입니까?이 C와의 CoreAudio의 구현은 다음과 같습니다
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData){
AudioSynthesiser * audioController = (AudioSynthesiser *)inRefCon;
// Get a pointer to the dataBuffer of the AudioBufferList
AudioSampleType * outA = (AudioSampleType *) ioData->mBuffers[0].mData;
if(!audioController->playing){
for (UInt32 i = 0; i < inNumberFrames; ++i){
outA[i] = (SInt16)0;
}
return noErr;
}
Track * track = &audioController->tracks[inBusNumber];
SynthInstrument * instrument = (SynthInstrument *)track;
float frequency_deviation;
float FMFrequency;
// Loop through the callback buffer, generating samples
for (UInt32 i = 0; i < inNumberFrames; ++i){
float signal = 0;
for (int x = 0; x < 10; x++) {
Note * note = track->notes_playing[x];
if(note){
//Envelope code removed
//Calculate signal
if (instrument->FMIndex) { //Apply FM
FMFrequency = note->frequency*instrument->FMRatio; //FM frequency is factor of note frequency.
note->FMPhase += FMFrequency/kGraphSampleRate; //Phase of modulator.
frequency_deviation = sinf(note->FMPhase * M_PI)*instrument->FMIndex*FMFrequency; //Frequency deviation. Max deviation is a factor of the FM frequency. Modulation is done by a sine wave.
note->phase += (note->frequency + frequency_deviation)/kGraphSampleRate; //Adjust phase with deviation
// Reset the phase value to prevent the float from overflowing
if (note->FMPhase >= 1){
note->FMPhase--;
}
}else{
note->phase += note->frequency/ kGraphSampleRate; //Adjust phase without deviation
}
// Calculate the next sample
signal += instrument->wave_function(note->phase,instrument->wave_parameter)*track->note_amplitude[x];
// Reset the phase value to prevent the float from overflowing
if (note->phase >= 1){
note->phase--;
}
} //Else nothing added
}
if(signal > 1.0){
signal = 1;
}else if(signal < -1.0){
signal = -1.0;
}
audioController->wave[audioController->wave_last] = signal;
if (audioController->wave_last == 499) {
audioController->wave_last = 0;
}else{
audioController->wave_last++;
}
outA[i] = (SInt16)(signal * 32767.0f);
}
return noErr;
}
답변 대단히 감사합니다.
이것은 http://dsp.stackexchange.com (또는 http://avp.stackexchange.com)에 좋은 질문 일 수 있습니다. – mtrw
좋아요, 시도해 보겠습니다. 감사! –