Thuật toán tổng hợp điều chế tần số


9

Dựa trên những gì tôi đọc được, tôi đã tạo ra một thuật toán để tổng hợp âm thanh FM. Tôi không chắc là tôi đã làm đúng chưa. Khi tạo một công cụ tổng hợp phần mềm, một chức năng được sử dụng để tạo bộ tạo dao động và bộ điều biến có thể được sử dụng để mô đun tần số của bộ dao động này. Tôi không biết nếu tổng hợp FM được cho là chỉ hoạt động để điều chỉnh sóng hình sin?

Thuật toán lấy hàm sóng dụng cụ và chỉ số và tỷ lệ bộ điều biến cho bộ điều chế tần số. Đối với mỗi lưu ý, nó lấy tần số và lưu giá trị pha cho bộ dao động sóng mang và bộ điều biến. Bộ điều biến luôn sử dụng sóng hình sin.

Đây là thuật toán trong mã giả:

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 

Vì vậy, nếu tần số của ghi chú là 100Hz, FMRatio được đặt ở mức 0,5 và FMIndex là 0,1, nó sẽ tạo ra các tần số nằm trong khoảng 95Hz đến 105Hz trong chu kỳ 50Hz. Đây có phải là cách làm chính xác. Các thử nghiệm của tôi cho thấy rằng nó không phải lúc nào cũng đúng, đặc biệt là khi điều chỉnh cưa và sóng vuông. Có thể điều chỉnh sóng cưa và sóng vuông như thế này hay chỉ dùng cho sóng hình sin?

Đây là cách triển khai trong C và 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;
}

Câu trả lời được đánh giá rất cao.


3
Tôi muốn đề nghị bạn đọc các cuộc thảo luận sau câu hỏi này . Mặc dù ở đây bạn không thực hiện chuyển đổi đột ngột về tần số như trong câu hỏi khác, việc duy trì tính liên tục pha trong tín hiệu FM là rất quan trọng và đảm bảo tín hiệu FM liên tục theo pha bất kể dạng sóng điều chế, cho dù là sóng hình sin hay răng cưa hay sóng vuông (có sự thay đổi đột ngột về tần suất!), sẽ giúp bạn tránh được nhiều vấn đề.
Dilip Sarwate

3
Không cần đọc đống mã lớn của bạn, thật đáng để hỏi: vấn đề chính xác là gì? Bạn nói rằng bạn không chắc liệu nó có hoạt động hay không. Điều gì đặc biệt khiến bạn nghĩ rằng nó không hoạt động?
Jason R

Câu trả lời:


2

Những gì bạn đang làm ở đây là điều chế pha. Đây là cách các synth 'FM' như Yamaha DX-7 hoạt động. Thông thường các bộ dao động tổng hợp được điều chỉnh trên thang âm nhạc, không phải là thang đo Hz tuyến tính thẳng. Vì vậy, điều chỉnh cao độ trực tiếp dẫn đến sự thay đổi cao độ không mong muốn, đó là lý do tại sao điều chế pha phù hợp hơn. Bạn có thể điều chỉnh bất kỳ hình dạng sóng nào, tuy nhiên những hình dạng phức tạp hơn sẽ bí danh dễ dàng hơn. Ngay cả một tội lỗi được điều chế cũng có thể là bí danh, vì vậy nó không bị cấm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.