2011-12-23 7 views
7

जो मैंने पढ़ा है उसके आधार पर, मैंने एफएम ध्वनि संश्लेषण के लिए एक एल्गोरिदम बनाया है। मुझे यकीन नहीं है कि मैंने सही किया है। सॉफ़्टवेयर synth instrument बनाते समय एक फ़ंक्शन का उपयोग ऑसीलेटर उत्पन्न करने के लिए किया जाता है और एक मॉड्यूलर का उपयोग इस ऑसीलेटर की आवृत्ति को मॉड्यूल करने के लिए किया जा सकता है। मुझे नहीं पता कि एफएम संश्लेषण केवल साइन लहरों को संशोधित करने के लिए काम करता है या नहीं?फ्रीक्वेंसी मॉड्यूलेशन सिंथेसिस एल्गोरिदम

एल्गोरिदम आवृत्ति मॉड्यूलर के लिए उपकरण तरंग समारोह और मॉड्यूलर सूचकांक और अनुपात लेता है। प्रत्येक नोट के लिए यह आवृत्ति लेता है और वाहक और मॉड्यूलर ऑसीलेटर के लिए चरण मान संग्रहीत करता है। मॉड्यूलेटर हमेशा साइन लहर का उपयोग करता है।

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 यह एक 50 हर्ट्ज में 95Hz और 105Hz के बीच जा रहा आवृत्तियों का उत्पादन करना चाहिए:

यह स्यूडोकोड में एल्गोरिथ्म है चक्र। क्या यह करने का सही तरीका है। मेरे परीक्षणों से पता चलता है कि यह हमेशा सही नहीं लगता है, खासकर जब देखा और वर्ग तरंगों को संशोधित करते हैं। क्या यह इस तरह देखा और वर्ग तरंगों को संशोधित करना ठीक है या यह केवल साइन लहरों के लिए है?

इस सी और 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; 
} 

जवाब बहुत सराहना कर रहे हैं।

+1

यह http://dsp.stackexchange.com (या शायद http://avp.stackexchange.com) के लिए एक अच्छा सवाल हो सकता है। – mtrw

+0

ठीक है, मैं इसे आज़माउंगा। धन्यवाद! –

उत्तर

2

अंत में मैंने चरण मॉड्यूलेशन का उपयोग करने का निर्णय लिया। मैंने पाया कि कई संश्लेषक चरण मॉड्यूलेशन का उपयोग करते हैं, भले ही उन्हें एफएम के साथ लेबल किया जाता है।

यह लागू करने के लिए आसान था:

signal += wave_function(note_phase * note_frequency/sample_rate + fm_index * sin(note_phase * fm_frequency * pi/sample_rate))*note_amplitude 
+0

क्या आप किसी भी संसाधन को उद्धृत करने के इच्छुक होंगे जिसे आपने सबसे अधिक उपयोगी पाया? मुझे 2-ऑपरेटर एफएम संश्लेषण के साथ कुछ अच्छी सफलता मिल रही है, लेकिन जब मैं श्रृंखला में 3 ऑपरेटरों को कैस्केड करने का प्रयास करता हूं तो निराशाजनक परिणाम प्राप्त कर रहा हूं। क्या आपने उस फैशन में एफएम का इस्तेमाल किया है? मैंने आपके द्वारा उद्धृत समीकरण और उसके एफएम चचेरे भाई का उपयोग किया है, लेकिन परिणाम समान हैं! –

3

अच्छा सवाल है, मैं कुछ विचार/विचारों ...

अपने मुख्य सवाल का जवाब देने की पेशकश करने की कोशिश करेंगे, हाँ यह साइन लहरों के अलावा अन्य waveforms व्यवस्थित करने के लिए पूरी तरह से ठीक है। वास्तव में, एफएम सबसे अच्छा है। मॉड्यूलिंग साइन लहरें बहुत ही उबाऊ ध्वनि आउटपुट देती हैं, लेकिन जब आप एक ही मॉड्यूलेशन के साथ अधिक जटिल तरंगों को इनपुट करते हैं, तो आपको अधिक दिलचस्प परिणाम मिलते हैं। एफवाईआई (यदि आप पहले से ही नहीं जानते हैं), सबसे प्रसिद्ध एफएम synth शायद Yamaha DX7 है जो अपने दिन में क्रांतिकारी था (और MIDI के साथ पहले कभी synths में से एक)।

उल्लेख करने की दूसरी बात यह है कि एफएम संश्लेषण डिजिटल युग की शुरुआत थी, इसलिए तरंगों को डिजिटल रूप से उत्पन्न किया गया था और इसलिए दिलचस्प ध्वनि बनाने के लिए साइन/वर्ग/त्रिकोण लहरों की तुलना में अधिक परिष्कृत तरंगों का उपयोग किया जाता था। यह बेहतर हो सकता है कि आपको एक बेहतर ध्वनि प्राप्त करने के लिए क्या करना है - बस एक तरंग लहर उत्पन्न करने के बजाय, जटिल तरंगों का उपयोग करें।

अपने कोड को देखकर, ऐसा लगता है कि आप एफएम सही तरीके से कर रहे हैं। हालांकि, मुझे लगता है कि मॉड्यूलेशन आवृत्ति सामान्य रूप से नोट आवृत्ति के एक अंश के बजाय तय की जाती है क्योंकि यह आपके कोड में है। यह कोशिश करने लायक हो सकता है और यह देखकर कि यह आपके जैसा दिख रहा है, उतना ही लगता है।

मुझे आशा है कि थोड़ा सा मदद मिलेगी।

+0

उत्तर के लिए धन्यवाद। मैंने अंत में एक चरण मॉड्यूलेशन के लिए जाने का फैसला किया। –

6

रेड आई:

अपने मुख्य सवाल का जवाब करने के लिए, हाँ यह साइन लहरों के अलावा अन्य waveforms व्यवस्थित करने के लिए पूरी तरह से ठीक है। वास्तव में, एफएम सबसे अच्छा है। मॉड्यूलिंग साइन लहरें बहुत ही उबाऊ ध्वनि आउटपुट देती हैं, लेकिन जब आप एक ही मॉड्यूलेशन के साथ अधिक जटिल तरंगों को इनपुट करते हैं, तो आपको अधिक दिलचस्प परिणाम मिलते हैं।

यह सबसे अधिक व्यापक रूप से संभवतः पूरी तरह से झूठा है। साइन लहरों के साथ साइन लहरों को मॉड्यूल करना जटिल की विस्तृत श्रृंखला बनाने और "उबाऊ" ध्वनियों को बनाने में पूरी तरह से सक्षम है।

इसके विपरीत, जटिल waveforms बड़े पैमाने पर sidebands जिसके परिणामस्वरूप की संख्या गुणा और उम्मीद के मुताबिक परिणाम बहुत अधिक प्राप्त करने के लिए कड़ी मेहनत करते हैं। एफएम के बारे में अधिकतर दस्तावेज - जो वास्तव में लगभग सामान्य समकक्ष PHASE मॉडुलन (पीएम) है, जिसमें कई आम मामलों में यामाहा द्वारा "एफएम" शामिल है - केवल साइन लहरों से संबंधित है।

FYI करें (मामले में आप पहले से ही नहीं है पता है), सबसे प्रसिद्ध एफएम सिंथ शायद यामाहा DX7 जो अपने दिन में क्रांतिकारी था है (और भी पहले से एक कभी मिडी साथ synths)।

दूसरी बात का उल्लेख है कि एफएम संश्लेषण डिजिटल युग तो waveforms डिजिटल उत्पन्न किया गया है और इसलिए साइन/वर्ग/त्रिकोण तरंगों की तुलना में अधिक परिष्कृत waveforms इस्तेमाल किया दिलचस्प लगता है बनाने के लिए की शुरुआत है। "

यह एक शक के बिना पूरी तरह से गलत है DX7 और कई जल्दी एफएम -। वास्तव में, प्रधानमंत्री - यामाहा द्वारा synths, केवल साइन लहरें, और की पेशकश की अभी तक के रूप में मैं ऊपर संकेत, वे अभी भी, कई में सक्षम कई गैर- "बोरिंग कर रहे हैं "लगता है। नहीं" और अधिक परिष्कृत waveforms "शामिल थे।

केवल बाद में यामाहा अन्य waveforms जोड़ने था, और उनकी उपयोगिता कुछ हद तक कुए है जैसा कि मैंने ऊपर बताया है, साइन लहरों द्वारा बनाई गई साइडबैंड की भविष्यवाणी की तुलना में स्थिर है।

यह हो सकता है आप एक बेहतर ध्वनि के लिए क्या करने की जरूरत -। जटिल waveforms का उपयोग करने के बजाय सिर्फ व्यवस्थित करने के लिए एक साइन लहर उत्पन्न "

या सिर्फ अच्छा व्यवस्था के साथ साइन तरंगों का उपयोग और पैरामीटर (अनुपात, सूचकांक, आदि) के संयोजन

तथ्य यह है कि साइन लहरों के साथ एफएम/पीएम तुरंत स्टूडियो-गुणवत्ता का उत्पादन नहीं करता है - या शायद एनालॉग-जैसे - कई उपयोगकर्ताओं के लिए परिणाम यह इंगित नहीं करते कि यह क्या है ऐसा करने में असमर्थ।

संबंधित मुद्दे