আমি যা পড়েছি তার উপর ভিত্তি করে, আমি এফএম শব্দ সংশ্লেষণের জন্য একটি অ্যালগরিদম তৈরি করেছি। আমি ঠিক করেছিলাম কিনা তা নিশ্চিত নই। একটি সফ্টওয়্যার সিন্থ ইনস্ট্রুমেন্ট তৈরি করার সময় একটি ফাংশন একটি দোলক উত্পন্ন করতে ব্যবহৃত হয় এবং এই দোলকের ফ্রিকোয়েন্সিটি মডিউল করার জন্য একটি মডিউলেটর ব্যবহার করা যেতে পারে। আমি জানি না যে এফএম সংশ্লেষণ কেবল সাইন ওয়েভগুলি সংশোধন করার জন্য কাজ করবে?
অ্যালগরিদম ফ্রিকোয়েন্সি মডুলেটারের জন্য যন্ত্র তরঙ্গ ফাংশন এবং মডিউলের সূচক এবং অনুপাত নেয়। প্রতিটি নোটের জন্য এটি ফ্রিকোয়েন্সি গ্রহণ করে এবং ক্যারিয়ার এবং মডুলেটর দোলকগুলির জন্য পর্বের মান সংরক্ষণ করে। মডুলেটর সর্বদা একটি সাইন ওয়েভ ব্যবহার করে।
এটি সিউডোকোডের আলগোরিদিম:
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
সুতরাং যদি নোটটির ফ্রিকোয়েন্সি 100Hz এ থাকে তবে FMRatio 0.5 তে সেট করা থাকে এবং FMIndex 0.1 হয় এটি 50Hz চক্রের 95Hz এবং 105Hz এর মধ্যে যাওয়ার ফ্রিকোয়েন্সি তৈরি করতে হবে। এটি কি এটি করার সঠিক উপায়। আমার পরীক্ষাগুলি দেখায় যে এটি সর্বদা ঠিক শোনা যায় না, বিশেষত যখন করাত এবং বর্গাকার তরঙ্গগুলিকে সংশোধন করার সময়। এর মতো করাত এবং বর্গাকার তরঙ্গগুলি সংশোধন করা ঠিক কি এটি কেবল সাইন ওয়েভগুলির জন্য?
এটি সি এবং কোর অডিওতে বাস্তবায়ন:
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;
}
উত্তরগুলি খুব প্রশংসা করা হয়।