Sine wave
Square wave

Triangle wave

Sawtooth wave

주기의 시작점에서 서서히 증가하여 끝까지 도달하는 파형임, 생긴게 톱날처럼 생겨서 톱니파라고 부름
모든 배수에서도 배음이 존재하기 때문에 풍부한 사운드가 특징임, 사각파의 경우에는 의 배음의 크기를 가지기 떄문에 배음이 큰편임.
// supersaw wave 생성예제
osc.initialise([](float x) {return std::sin(x); }, 128);
for (int i = 0; i < 7; ++i)
{
subOscl[i].initialise([](float x)
{
// 기본 톱니파(sawtooth) 람다
return x / juce::MathConstants<float>::pi;
},
128); // 초기 해상도 설정 (테스트용), 이후 prepareSuperSaw에서 재초기화
}
/*Sine wave */
osc.initialise(
[](float x) { return std::sin(x); },
tableResolution);
/*Square wave */
osc.initialise(
[](float x) {return x < 0.0f ? -1.0f : +1.0f;},
tableResolution);
/*Triangle wave */
osc.initialise(
[](float x)
{
return std::asin(std::sin(x)) * (2.0f / juce::MathConstants<float>::pi);
},
tableResolution);
/*Sawtooth wave */
osc.initialise(
[](float x)
{
return (x / juce::MathConstants<float>::pi);
},
tableResolution);
//1. Oscilator 선언
juce::dsp::Oscillator<float> osc;
void Oscillator::setSampleRate(double input_rate){
sampleRate = input_rate;
//2. Sampling rate 설정
juce::dsp::ProcessSpec spec;
spec.sampleRate = sampleRate;
spec.maximumBlockSize = 512; //오디오 버퍼 사이즈 설정
spec.numChannels = 1; //오디오 채널 설정
osc.prepare(spec);
//3. 주파수 설정
osc.setFrequency(freq);
//4. 오디오 처리 구현
void Oscillator::getNextSample(juce::AudioBuffer<float>& buffer, int startSample, int numSamples)
{
for (int s = 0; s < numSamples; ++s)
{
float outSample = 0.0f;
if (currentWaveType == WaveType::SuperSaw)
outSample = SuperSaw();
else
outSample = osc.processSample(0.0f);
for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
buffer.addSample(ch, startSample + s, outSample);
}
}
대략적으로 웨이브테이블의 사이즈가 128이라고 하면 의 샘플간 위상차에 대한 공식은
으로 계산이 가능함 즉 샘플하나당 간격이 0.05rad 정도 차이가 난다고 보면됨, 여기서 저 파형간의 샘플링간격이 짧을수록 소리 고주파수에서도 손실없이 대응이 가능
최종적인 순서는 아래 과정을 계속 반복하여 버퍼에 넣어주면됨
// 1. 현재 위상을 기준으로 인덱스값 얻기
output[i] = interpolateWavetable(currentPhase);
// 2. 주파수에 따른 Phase increment 값 합산
currentPhase += phase_increment;
// 3. 주파수에 따른 Phase increment 값 합산
if (currentPhase >= 2pi)
currentPhase = 0;