JUCE学习笔记07-自定义正弦振荡器类

JUCE学习笔记07——自定义正弦振荡器类

一、变量:

频率、采样率、当前角度/相位、角度/相位增量、样本值(振幅)

频率(frequency):

每秒完整周期的次数

采样率(sampleRate):

每秒的采样数

采样值(currentSample):

当前采样点的振幅——音频系统最终实现声音输出的数据

当前角度/相位(currentAngle):

当前采样点在周期内的位置

角度/相位增量(angleDelta):

下个采样点与当前采样点之间的角度/相位增量

二、公式:

1.frequency/sampleRate:

单个采样数与一个周期采样数的比率

2.angleDelta=(frequency/sampleRate)*2pi:

相邻采样点之间的角度/相位差(一个周期为2pi)

3.currentAngle=currentAngle+angleDelta

当前角度/相位与角度/相位增量的和为下一个样本的角度/相位

4.currentSample=sin(currentAngle)

当前样本的角度/相位计算正弦值

三、实现:

创建正弦振荡器类
1.成员函数setFrequency()设置波形频率,计算相邻样本间的角度/相位差
private:
	float angleDelta;	        //角度/相位增量
    float currentAngle;		//存储当前角度
void SinWave::setFrequency(float freq, float sampleRate)
{
	angleDelta = (freq*MathConstants<float>::twoPi) / sampleRate;
}
2.函数updateAngle()更新当前角度/相位
void SinWaveOsc::updateAngle()
{
	currentAngle += angleDelda;//当前角度+增量获取新角度
	if (currentAngle >= MathConstants<float>::twoPi)
		currentAngle -= MathConstants<float>::twoPi;//限制角度在2Π内
}
3.getNextSample()函数计算波形采样点的振幅值
float SinWaveOsc::getNextSample()
{
	auto currentSample = sin(currentAngle);
	updateAngle();
	return currentSample;
}

SinWaveOsc类完整代码:

//SinWaveOsc.h
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"

class SinWaveOsc {

public:
	//==============================================
	SinWaveOsc();
	~SinWaveOsc();

	//==============================================
	void setFrequancy(float freq, float sampleRate);
	float getNextSample();
	void updateAngle();

private:
	float currentAngle;
	float angleDelda;

};

//SinWaveOsc.cpp
#include "SinWaveOsc.h"

//========================================================================
SinWaveOsc::SinWaveOsc()
{
	currentAngle = 0.0f;
	angleDelda = 0.0f;
}

SinWaveOsc::~SinWaveOsc()
{
}

//========================================================================
void SinWaveOsc::setFrequancy(float freq,float sampleRate)
{
	angleDelda = freq / sampleRate * MathConstants<float>::twoPi;
}

float SinWaveOsc::getNextSample()
{
	auto currentSample = sin(currentAngle);
	updateAngle();
	return currentSample;
}

void SinWaveOsc::updateAngle()
{
	currentAngle += angleDelda;
	if (currentAngle >= MathConstants<float>::twoPi)
		currentAngle -= MathConstants<float>::twoPi;
}
创建正弦振荡器对象在主组件中实现声音播放
//MainComponent.h
#include "../JuceLibraryCode/JuceHeader.h"
#include "SinWaveOsc.h"

//==============================================================================
class MainComponent   : public AudioAppComponent
{
public:
    //==============================================================================
    MainComponent();
    ~MainComponent();

    //==============================================================================
    void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
    void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override;
    void releaseResources() override;

    //==============================================================================
    void paint (Graphics& g) override;
    void resized() override;

private:
    //==============================================================================
	SinWaveOsc sinWaveOsc;
	float level;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

//MainComponent.cpp
#include "MainComponent.h"
//==============================================================================
MainComponent::MainComponent()
{
    setSize (600, 100);

    if (RuntimePermissions::isRequired (RuntimePermissions::recordAudio)
        && ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
    {
        RuntimePermissions::request (RuntimePermissions::recordAudio,
                                     [&] (bool granted) { if (granted)  setAudioChannels (2, 2); });
    }
    else
    {
        setAudioChannels (0, 2);
    }
}

MainComponent::~MainComponent()
{
    shutdownAudio();
}

//==============================================================================
void MainComponent::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
	sinWaveOsc.setFrequancy(220, sampleRate);
	level = 0.1f;  //控制振幅(音量)
}

void MainComponent::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
	auto* leftChannel = bufferToFill.buffer->getWritePointer(0, bufferToFill.startSample);
	auto* rightChannel = bufferToFill.buffer->getWritePointer(1, bufferToFill.startSample);

    bufferToFill.clearActiveBufferRegion();

	for (int sample = 0; sample < bufferToFill.numSamples; ++sample)
	{
		leftChannel[sample] = sinWaveOsc.getNextSample()*level;
		rightChannel[sample] = sinWaveOsc.getNextSample()*level;
	}
}

void MainComponent::releaseResources()
{
}

//==============================================================================
void MainComponent::paint (Graphics& g)
{
}

void MainComponent::resized()
{
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值