# 開發紀錄(week3) ### Note --- - f : Hz (一秒震盪幾次) - f<sub>s</sub> : 取樣頻率 (一秒取樣幾次) - T : 週期 cycle time : sec (一次震盪幾秒) - ω = 2πf = 2π/T = 角度差/週期 (一秒走多少角度) - sin(ωt+θ) = sin(2πf * t+θ) = sin(2πf * n/f<sub>s</sub>+θ) - t為時間 - n為index(第幾個angleIncrement) - sin(一秒走多少角度*一次取樣花幾秒+θ=一次取樣走多少角度+θ) <br> - - 下兩圖的x,y軸是相對應的, 事實上x軸並非實數軸, 而是度數 - sin(x)值為對應的y值 - sin(currentAngle) = sin(x) ![link text](https://www.researchgate.net/publication/341812787/figure/fig1/AS:897790007836673@1591061226081/The-unit-circle-used-for-deriving-sine-and-cosine-functions.png) ![link text](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Sine.svg/885px-Sine.svg.png) <br> - angleIncrement: 2πf * 1/f<sub>s</sub> = 一秒走多少角度*一次取樣花幾秒 = 一次取樣走多少角度 - 由getSampleRte()取得f<sub>s</sub> ```C++ void SynthVoice::startNote (int midiNoteNumber, float velocity, juce::SynthesiserSound* sound, int currentPitchWheelPosition){ noteMidiNumber = midiNoteNumber; frequency = juce::MidiMessage::getMidiNoteInHertz(midiNoteNumber); currentAngle = 0.f; angleIncrement = frequency / getSampleRate() * juce::MathConstants<float>::twoPi; tailOff = 0.0; } ``` <br> - - numSamples : 是一個block有多少存取點, 每次以block為單位回傳處理好的值, 所以for loop會執行一個block的次數 - Sin(currentAngle)的currenAngle會在每一次跑for loop時增加一個angleIncrement=一秒走多少角度*一次取樣花幾秒 &rarr; 一次取樣走多少角度 ```C++ void SynthVoice::renderNextBlock (juce::AudioBuffer<float> &outputBuffer, int startSample, int numSamples){ if (tailOff > 0.0){ for (int i = startSample; i < (startSample + numSamples); i++){ float value = std::sin(currentAngle) * level * tailOff; outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; tailOff *= 0.99; if (tailOff <= 0.05){ clearCurrentNote(); angleIncrement = 0.0; level = 0.0; break; } } } else{ for (int i = startSample; i < (startSample + numSamples); i++){ float value = std::sin(currentAngle) * level; outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; } } } ``` <br> ### Wave shape --- ![link text](https://quorumlanguage.com/media/dsp/waveforms.png) <br> ### Sine wave --- ``` for (int i = startSample; i < (startSample + numSamples); i++){ float value = std::sin(currentAngle) * level * tailOff; outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; tailOff *= 0.99; } ``` <br> ### Triangle wave --- - - currentAngle < 1/2π: equation=2/π * x - 1/2π < currentAngle < 3/2π: equation=-2/π * x + 2 - currentAngle > 3/2π: equation=2/π * x - 4 ``` for (int i = startSample; i < (startSample + numSamples); i++){ if (currentAngle > juce::MathConstants<float>::twoPi){ currentAngle -= juce::MathConstants<float>::twoPi; } if(currentAngle < 1/2 * juce::MathConstants<float>::pi{ float value = 2 / juce::MathConstants<float>::pi * currentAngle * level * tailOff; } else if(1/2 * juce::MathConstants<float>::pi < currentAngle < 3/2 * juce::MathConstants<float>::pi){ float value = (-2 / juce::MathConstants<float>::pi * currentAngle + 2) * level * tailOff; } else if (currentAngle > 3/2 * juce::MathConstants<float>::pi){ float value = (2 / juce::MathConstants<float>::pi * currentAngle - 4) * level * tailOff; } outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; tailOff *= 0.99; } ``` <br> ### Sawtooth wave - equation=1/π * x - 1 --- ``` for (int i = startSample; i < (startSample + numSamples); i++){ if (currentAngle > juce::MathConstants<float>::twoPi){ currentAngle -= juce::MathConstants<float>::twoPi; } float value = (1 / juce::MathConstants<float>::pi * currentAngle - 1) * level * tailOff; outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; tailOff *= 0.99; } ``` <br> ### Square wave --- ``` for (int i = startSample; i < (startSample + numSamples); i++){ if(std::sin(currentAngle) > 0){ float value = 1 * level * tailOff; } else if(std::sin(currentAngle) < 0){ float value = -1 * level * tailOff; } outputBuffer.addSample(0, i, value); outputBuffer.addSample(1, i, value); currentAngle += angleIncrement; tailOff *= 0.99; } ``` <br> ### Settings - 每次開新專案都要Debug一次