#include "pch.h"
#include "Sequencer.h"
+namespace sf {
-Sequencer::Sequencer(void)
+ struct Sequencer::impl
+ {
+ impl(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format)
+ : synth_(synth), format_(format) ,tempo_(120.0f),timebase_(480.0f),meter_(4.0f),meterDiv_(4.0f),
+ currentTime_(0)
+ {
+ Update();
+ for(int i = 0,end = synth_.Voices();i < end;++i)
+ {
+ gateBuffer_.push_back(0);
+ currentIndexs_.push_back(0);
+ SequenceTracks_.push_back(SequenceDatasType());
+ }
+ }
+
+ void Update()
+ {
+ // stepDeltaTime_ = (int64_t)((((double)meter_ * (double)tempo_ * (double)format_.Format.nSamplesPerSec) / ((double)meterDiv_ * 60.0 * (double)timebase_ )) * (double)(0x100000000));
+ stepDeltaTime_ = (int64_t)(( ((double)tempo_ * (double)timebase_ ) / (60.0 * (double)format_.Format.nSamplesPerSec)) * (double)(0x100000000));
+ }
+
+
+
+ void Process()
+ {
+ currentTime_ += stepDeltaTime_;
+ int currentTime = currentTime_ >> 32;
+ for(int i = 0,end = SequenceTracks_.size();i < end;++i)
+ {
+ SequenceDatasType& track(SequenceTracks_[i]);
+ if(!track.empty() && track.size() > currentIndexs_[i]) {
+ if(currentTime >= track[currentIndexs_[i]].step)
+ {
+ do
+ {
+ SequenceData& d(SequenceTracks_[i][currentIndexs_[i]]);
+ synth_.NoteOn(i,d.pitch,d.velocity);
+ gateBuffer_[i] = (int64_t)d.gateTime << 32;
+ currentIndexs_[i] = currentIndexs_[i] + 1;
+ if(currentIndexs_[i] >= track.size())
+ {
+ break;
+ }
+ } while(currentTime >= SequenceTracks_[i][currentIndexs_[i]].step);
+ }
+ }
+ // \83Q\81[\83g\83^\83C\83\80\82Ì\8f\88\97\9d
+ if(gateBuffer_[i] > 0)
+ {
+ gateBuffer_[i] -= stepDeltaTime_;
+ if(gateBuffer_[i] <= 0)
+ {
+ gateBuffer_[i] = 0;
+ synth_.NoteOff(i);
+ }
+ }
+ }
+ }
+
+ float TimeBase() const {return timebase_;}
+ void TimeBase(float v) {timebase_ = v;Update();}
+
+ float Tempo() const {return tempo_;}
+ void Tempo(float v) {tempo_ = v;Update();}
+
+ std::vector<SequenceDatasType>& SequenceTracks() {return SequenceTracks_;}
+
+ private:
+
+ WAVEFORMATEXTENSIBLE& format_;
+ float tempo_;
+ float timebase_;
+ int meter_;
+ int meterDiv_;
+ int64_t stepDeltaTime_;
+ int64_t currentTime_;
+ std::vector<int> currentIndexs_;
+ std::vector<int64_t> gateBuffer_;
+ SequenceTracksType SequenceTracks_;
+ Synthesizer& synth_;
+ };
+
+Sequencer::Sequencer(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format) : impl_(new impl(synth,format))
{
-}
+}
-Sequencer::~Sequencer(void)
+Sequencer::~Sequencer()
{
+
+}
+
+float Sequencer::TimeBase() const {return impl_->TimeBase();}
+void Sequencer::TimeBase(float v) {impl_->TimeBase(v);}
+
+float Sequencer::Tempo() const {return impl_->Tempo();}
+void Sequencer::Tempo(float v) {impl_->Tempo(v);}
+
+void Sequencer::Process() {impl_->Process();}
+
+ SequenceTracksType& Sequencer::SequenceTracks() {return impl_->SequenceTracks();}
+
}
#pragma once
-class Sequencer
-{
-public:
- Sequencer(void);
- ~Sequencer(void);
-};
+#include "WaveTableSynth.h"
+namespace sf {
+ enum struct SequenceCommand {
+ Note
+ };
+
+ struct SequenceData
+ {
+ SequenceData () : step(0.0f),pitch(0.0f),velocity(0.0f),gateTime(0.0f){};
+ SequenceData(SequenceCommand c,int s,float p,float v,int g )
+ : cmd(c),step(s),pitch(p),velocity(v),gateTime(g) {};
+ SequenceData(SequenceData& src)
+ : cmd(src.cmd),step(src.step),pitch(src.pitch),velocity(src.velocity),gateTime(src.gateTime) {}
+
+ SequenceData(SequenceData&& src)
+ : cmd(std::move(src.cmd)),step(std::move(src.step)),pitch(std::move(src.pitch)),velocity(std::move(src.velocity)),gateTime(std::move(src.gateTime)) {}
+
+ SequenceData& operator=(SequenceData& src)
+ {
+ if(this != &src)
+ {
+ cmd = src.cmd;
+ step = src.step;
+ pitch = src.pitch;
+ velocity = src.velocity;
+ gateTime = src.gateTime;
+ }
+ return *this;
+ }
+
+ SequenceData& operator=(SequenceData&& src)
+ {
+ if(this != &src)
+ {
+ cmd = std::move(src.cmd);
+ step = std::move(src.step);
+ pitch = std::move(src.pitch);
+ velocity = std::move(src.velocity);
+ gateTime = std::move(src.gateTime);
+ }
+ return *this;
+ }
+
+ SequenceCommand cmd;
+ int step;
+ float pitch;
+ float velocity;
+ int gateTime;
+ };
+
+ typedef std::vector<SequenceData> SequenceDatasType;
+ typedef std::vector<SequenceDatasType> SequenceTracksType;
+
+ struct Sequencer
+ {
+ public:
+ Sequencer(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format);
+ void Process();
+ ~Sequencer();
+
+ float TimeBase() const;
+ void TimeBase(float v);
+
+ float Tempo() const;
+ void Tempo(float v);
+ SequenceTracksType& SequenceTracks();
+ private:
+ struct impl;
+ std::unique_ptr<impl> impl_;
+ };
+}
<ClInclude Include="sf_com.h" />
<ClInclude Include="sf_memory.h" />
<ClInclude Include="SoundDriver.h" />
+ <ClInclude Include="TestSong.h" />
<ClInclude Include="WaveTableSynth.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Sequencer.cpp" />
<ClCompile Include="sf_com.cpp" />
<ClCompile Include="SoundDriver.cpp" />
+ <ClCompile Include="TestSong.cpp" />
<ClCompile Include="WaveTableSynth.cpp">
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AssemblyAndSourceCode</AssemblerOutput>
</ClCompile>
#include "pch.h"
#include "sf_memory.h"
#include "SoundDriver.h"
-
using namespace std;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
namespace sf {
-
SoundDriver::SoundDriver() : bufferIndex_(0),eventHolder_(nullptr),synth_(nullptr)
{
//::AvMMAvSetMmThreadCharacteristics
ThrowIfErr(audioClient_->GetService(__uuidof(IAudioRenderClient),&audioRenderClient_));
eventHolder_.reset(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE));
audioClient_->SetEventHandle(eventHolder_.get());
- synth_.reset(new WaveTableSynth(format_));
+ synth_.reset(new Synthesizer(format_));
+ sequencer_.reset(new Sequencer(*synth_.get(),format_));
+ sequencer_->Tempo(220.0f);
- synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
+ TestSong song(sequencer_->SequenceTracks());
+
+ ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
BYTE* rawBuffer;
ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
audioRenderClient_->ReleaseBuffer(bufferSize_,0);
bufferIndex_ = (bufferIndex_ + 1) & 0x1;
- synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
+ ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
ThrowIfErr(audioClient_->Start());
}
audioClient_->Reset();
}
+ void SoundDriver::ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
+ {
+ // \8d¡\82Ì\82Æ\82±\82ë\8fo\97Í\82Í\83X\83e\83\8c\83I\91O\92ñ
+ //for(int j = 0;j < voices_.size();++j)
+ //{
+ // voices_[j].Process(buffer);
+ // *ptr += buffer[0];
+ // *(ptr + 1) += buffer[1];
+ //}
+ float *ptr = arr.get();
+
+ ZeroMemory(ptr,bufferByteCount_);
+
+ for(int i = 0;i < bufferSize;++i)
+ {
+ sequencer_->Process();
+ synth_->Process(ptr);
+ ptr += 2;
+ }
+ }
+
void SoundDriver::Render()
{
::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
::memcpy(rawBuffer,buffer_[bufferIndex_].get(),bufferByteCount_);
audioRenderClient_->ReleaseBuffer(bufferSize_,0);
bufferIndex_ = (bufferIndex_ + 1) & 0x1;
- ZeroMemory(buffer_[bufferIndex_].get(),bufferByteCount_);
- synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
+ ProcessBuffer(buffer_[bufferIndex_],bufferSize_);
}
}
}
#pragma once
#include "WaveTableSynth.h"
+#include "Sequencer.h"
+#include "TestSong.h"
typedef Microsoft::WRL::ComPtr<IAudioClient2> IAudioClient2Ptr;
//typedef Microsoft::WRL::ComPtr<IAudioClock2> IAudioClock2Ptr;
~SoundDriver();
void Render();
-
+ void ProcessBuffer(boost::shared_array<float> arr,int bufferSize);
private:
IAudioClient2Ptr audioClient_;
uint32_t bufferSize_;
IAudioRenderClientPtr audioRenderClient_;
WAVEFORMATEXTENSIBLE format_;
sf::handle_holder eventHolder_;
- std::unique_ptr<sf::WaveTableSynth> synth_;
+ std::unique_ptr<sf::Synthesizer> synth_;
+ std::unique_ptr<sf::Sequencer> sequencer_;
boost::shared_array<float> buffer_[2];
int bufferIndex_;
int bufferByteCount_;
--- /dev/null
+#include "pch.h"
+#include <array>
+#include "WaveTableSynth.h"
+#include "Sequencer.h"
+#include "TestSong.h"
+
+namespace sf {
+
+
+
+ TestSong::TestSong(SequenceTracksType& tracks) : tracks_(tracks)
+ {
+ for(float i = -5.0f;i < 5.0f;++i)
+ {
+ noteTable_.push_back(powf(2.0f,-9.0f/12.0f + i ));//C
+ noteTable_.push_back(powf(2.0f,-8.0f/12.0f + i ));//C#
+ noteTable_.push_back(powf(2.0f,-7.0f/12.0f + i ));//D
+ noteTable_.push_back(powf(2.0f,-6.0f/12.0f + i ));//D#
+ noteTable_.push_back(powf(2.0f,-5.0f/12.0f + i ));//E
+ noteTable_.push_back(powf(2.0f,-4.0f/12.0f + i ));//F
+ noteTable_.push_back(powf(2.0f,-3.0f/12.0f + i ));//F#
+ noteTable_.push_back(powf(2.0f,-2.0f/12.0f + i ));//G
+ noteTable_.push_back(powf(2.0f,-1.0f/12.0f + i ));//G#4
+ noteTable_.push_back(powf(2.0f,0.0f + i ));//A4
+ noteTable_.push_back(powf(2.0f,1.0f/12.0f + i ));//A#4
+ noteTable_.push_back(powf(2.0f,2.0f/12.0f + i ));//B4
+ }
+
+ for(int i = 0;i < tracks.size();++i)
+ {
+ stepCounters_.push_back(0);
+ }
+
+ //CreateTestTone();
+ CreateMappyData();
+ // CreateCosmicSurfin();
+
+
+ }
+
+ void TestSong::CreateMappyData()
+ {
+ AddNote(0,480,Note::E,5,1.0f,120);
+ AddNote(0,480,Note::B,5,1.0f,120);
+ AddNote(0,480,Note::AS,5,1.0f,120);
+ AddNote(0,360,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::C,6,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+ AddNote(0,120,Note::B,5,1.0f,30);
+
+ AddNote(0,480,Note::A,5,1.0f,90);
+ AddNote(0,480,Note::B,5,1.0f,90);
+ AddNote(0,360,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::G,5,1.0f,90);
+ AddNote(0,360,Note::E,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+
+ AddNote(0,480,Note::D,5,1.0f,90);
+ AddNote(0,480,Note::A,5,1.0f,90);
+ AddNote(0,480,Note::GS,5,1.0f,90);
+ AddNote(0,360,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+ AddNote(0,120,Note::A,5,1.0f,90);
+
+ AddNote(0,480,Note::G,5,1.0f,90);
+ AddNote(0,480,Note::A,5,1.0f,90);
+ AddNote(0,360,Note::G,5,1.0f,90);
+ AddNote(0,480,Note::E,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+
+ AddNote(0,360,Note::B,3,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+ AddNote(0,360,Note::G,5,1.0f,90);
+ AddNote(0,120,Note::B,3,1.0f,90);
+ AddNote(0,360,Note::D,5,1.0f,90);
+ AddNote(0,120,Note::G,5,1.0f,90);
+ AddNote(0,360,Note::B,3,1.0f,90);
+ AddNote(0,120,Note::D,5,1.0f,90);
+
+ AddNote(0,360,Note::C,5,1.0f,90);
+ AddNote(0,120,Note::E,5,1.0f,90);
+ AddNote(0,360,Note::G,5,1.0f,90);
+ AddNote(0,120,Note::CS,5,1.0f,90);
+ AddNote(0,360,Note::E,5,1.0f,90);
+ AddNote(0,120,Note::G,5,1.0f,90);
+ AddNote(0,360,Note::CS,5,1.0f,90);
+ AddNote(0,120,Note::E,5,1.0f,90);
+
+ AddRest(0,480);
+ AddNote(0,360,Note::B,5,1.0f,90);
+ AddNote(0,120,Note::AS,5,1.0f,90);
+ AddNote(0,480,Note::A,5,1.0f,90);
+ AddNote(0,360,Note::D,5,1.0f,90);
+ AddNote(0,600,Note::G,5,1.0f,90);
+
+ AddNote(0,480,Note::G,5,1.0f,90);
+ AddNote(0,480,Note::FS,5,1.0f,90);
+ AddNote(0,480,Note::E,5,1.0f,90);
+
+ //
+
+ AddNote(2/*channel*/,480/*step*/,Note::E /*\89¹\8aK*/,5/*octave*/,1.0f/*velocity*/,10 /*gatetime*/,0.002f/*ofset*/);
+ AddNote(2,480,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::AS,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::C,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,6,1.0f,10,0.002f);
+
+ AddNote(2,480,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::E,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+
+ AddNote(2,480,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::GS,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::A,5,1.0f,10,0.002f);
+
+ AddNote(2,480,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::E,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+
+ AddNote(2,360,Note::B,3,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::B,3,1.0f,10,0.002f);
+ AddNote(2,360,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::B,3,1.0f,10,0.002f);
+ AddNote(2,120,Note::D,5,1.0f,10,0.002f);
+
+ AddNote(2,360,Note::C,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::E,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::CS,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::E,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::CS,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::E,5,1.0f,10,0.002f);
+
+ AddRest(2,480);
+ AddNote(2,360,Note::B,5,1.0f,10,0.002f);
+ AddNote(2,120,Note::AS,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::A,5,1.0f,10,0.002f);
+ AddNote(2,360,Note::D,5,1.0f,10,0.002f);
+ AddNote(2,600,Note::G,5,1.0f,10,0.002f);
+
+ AddNote(2,480,Note::G,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::FS,5,1.0f,10,0.002f);
+ AddNote(2,480,Note::E,5,1.0f,10,0.002f);
+
+ //
+
+ AddNote(1,480,Note::E,2,1.0f,90);
+ AddRest(1,480);
+ AddNote(1,480,Note::B,1,1.0f,90);
+ AddRest(1,360);
+ AddNote(1,120,Note::E,2,1.0f,90);
+
+ AddRest(1,360);
+ AddNote(1,120,Note::E,2,1.0f,90);
+ AddNote(1,480,Note::B,1,1.0f,90);
+ AddNote(1,360,Note::E,2,1.0f,90);
+ AddNote(1,120,Note::FS,2,1.0f,90);
+ AddNote(1,480,Note::GS,2,1.0f,90);
+
+ AddNote(1,480,Note::A,2,1.0f,90);
+ AddRest(1,480);
+ AddNote(1,480,Note::E,2,1.0f,90);
+ AddRest(1,360);
+ AddNote(1,120,Note::A,2,1.0f,90);
+
+ AddRest(1,360);
+ AddNote(1,120,Note::A,2,1.0f,90);
+ AddNote(1,480,Note::G,2,1.0f,90);
+ AddNote(1,480,Note::FS,2,1.0f,90);
+ AddNote(1,480,Note::E,2,1.0f,90);
+
+ AddNote(1,480,Note::D,2,1.0f,90);
+ AddRest(1,480);
+ AddNote(1,480,Note::A,1,1.0f,90);
+ AddRest(1,360);
+ AddNote(1,120,Note::D,2,1.0f,90);
+
+ AddRest(1,360);
+ AddNote(1,120,Note::D,2,1.0f,90);
+ AddNote(1,480,Note::A,1,1.0f,90);
+ AddNote(1,360,Note::D,2,1.0f,90);
+ AddNote(1,120,Note::E,2,1.0f,90);
+ AddNote(1,480,Note::FS,2,1.0f,90);
+ }
+
+ void TestSong::CreateTestTone()
+ {
+ for(int j = 0;j < 5;++j){
+ for(int i = 2;i < 9;++i)
+ {
+ AddNote(0,960,Note::C,i,1.0f,600);
+ AddNote(0,960,Note::D,i,1.0f,600);
+ AddNote(0,960,Note::E,i,1.0f,600);
+ AddNote(0,960,Note::F,i,1.0f,600);
+ AddNote(0,960,Note::G,i,1.0f,600);
+ AddNote(0,960,Note::A,i,1.0f,600);
+ AddNote(0,960,Note::B,i,1.0f,600);
+ }
+ }
+ }
+
+ void TestSong::CreateCosmicSurfin()
+ {
+
+ for(int i = 0;i < 8;++i){
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+ AddNote(0,240,Note::A,2,1.0f,190);
+ AddNote(0,240,Note::A,3,1.0f,190);
+ AddNote(0,240,Note::G,2,1.0f,190);
+ AddNote(0,240,Note::G,3,1.0f,190);
+
+ AddNote(0,240,Note::D,3,1.0f,190);
+ AddNote(0,240,Note::D,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::D,3,1.0f,190);
+ AddNote(0,240,Note::D,4,1.0f,190);
+ AddNote(0,240,Note::D,3,1.0f,190);
+ AddNote(0,240,Note::D,4,1.0f,190);
+
+ AddNote(0,240,Note::F,3,1.0f,190);
+ AddNote(0,240,Note::F,4,1.0f,190);
+ AddNote(0,240,Note::DS,3,1.0f,190);
+ AddNote(0,240,Note::DS,4,1.0f,190);
+ AddNote(0,240,Note::F,3,1.0f,190);
+ AddNote(0,240,Note::F,4,1.0f,190);
+ AddNote(0,240,Note::F,3,1.0f,190);
+ AddNote(0,240,Note::F,4,1.0f,190);
+
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::C,3,1.0f,190);
+ AddNote(0,240,Note::C,4,1.0f,190);
+ AddNote(0,240,Note::B,2,1.0f,190);
+ AddNote(0,240,Note::B,3,1.0f,190);
+
+ }
+
+ }
+
+
+ void TestSong::AddNote(int channel,int step,float pitch,float velocity,int gatetime)
+ {
+ tracks_[channel].push_back(SequenceData(SequenceCommand::Note,stepCounters_[channel],pitch,velocity,gatetime));
+ stepCounters_[channel] += step;
+ }
+
+ void TestSong::AddNote(int channel,int step,Note note,int octave,float velocity,int gatetime,float detune )
+ {
+ tracks_[channel].push_back(SequenceData(SequenceCommand::Note,stepCounters_[channel],GetPitch(note,octave) + detune,velocity,gatetime));
+ stepCounters_[channel] += step;
+ }
+
+ void TestSong::AddRest(int channel,int step)
+ {
+ stepCounters_[channel] += step;
+ }
+
+ float TestSong::GetPitch(Note note,int octave)
+ {
+ return noteTable_[(int)note + octave * 12];
+ }
+
+ TestSong::~TestSong(void)
+ {
+ }
+}
--- /dev/null
+#pragma once
+namespace sf {
+ enum struct Note
+ {
+ C,CS,D,DS,E,F,FS,G,GS,A,AS,B
+ };
+
+ class TestSong
+ {
+ public:
+ TestSong(SequenceTracksType& tracks);
+ void AddNote(int channel,int step,float pitch,float velocity,int gatetime);
+ void AddNote(int channel,int step,Note note,int octave,float velocity,int gatetime,float detune = 0.0f);
+ void AddRest(int channel,int step);
+ void CreateMappyData();
+ void CreateTestTone();
+ void CreateCosmicSurfin();
+ float GetPitch(Note note ,int octave);
+ ~TestSong();
+ private:
+ std::vector<int> stepCounters_;
+ std::vector<float> noteTable_;
+ SequenceTracksType& tracks_;
+ };
+}
+
namespace sf {
+ std::vector<Synthesizer::WaveTable> Synthesizer::WaveTable::WaveTables;
+
void makeWaveFormat(WAVEFORMATEXTENSIBLE& format,
int sample_rate = 44100,int channels = 2,int bits_per_sample = 32,int valid_bits_per_sample = 32,
uint32_t type = WAVE_FORMAT_EXTENSIBLE,
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
};
- struct WaveTableSynth::impl {
+ void Synthesizer::WaveTableOscillator::WaveTable(Synthesizer::WaveTable *p)
+ {
+ waveTable_ = p;
+ if(waveTable_->stereo)
+ {
+ processor_ = std::bind(&sf::Synthesizer::WaveTableOscillator::ProcessStereo,this,_1,_2,_3);
+ } else {
+ processor_ = std::bind(&sf::Synthesizer::WaveTableOscillator::ProcessMono,this,_1,_2,_3);
+ }
+
+ }
+
+ struct Synthesizer::impl {
impl(){};
- explicit impl(WAVEFORMATEXTENSIBLE& format) : format_(format)
+ explicit impl(WAVEFORMATEXTENSIBLE& format,int channel) : format_(format)
{
// \8b\98\94g\83e\81[\83u\83\8b\82ð\8dì\82é
{
WaveTable sawtbl;
- sawtbl.SampleRate(440.0f);
- sawtbl.BasePitch(1.0f);
- sawtbl.Stereo(false);
+ sawtbl.sampleRate = 440.0f;
+ sawtbl.basePitch = 0.0f;
+ sawtbl.stereo = false;
float v = -1.0f,d = 2.0f / 32.0f;
for(int i = 0;i < 32;++i)
{
// if(i < 15) v = -1.0f; else v = 1.0f;
- sawtbl.WaveData().push_back(v) ;
+ sawtbl.waveData.push_back(v) ;
v += d;
}
- waveTable_.push_back(sawtbl);
+ WaveTable::WaveTables.push_back(std::move(sawtbl));
}
// \8bé\8c`\94g\83e\81[\83u\83\8b\82ð\8dì\82é
{
WaveTable squaretbl;
- squaretbl.SampleRate(440.0f);
- squaretbl.BasePitch(1.0f);
- squaretbl.Stereo(false);
+ squaretbl.sampleRate = 440.0f;
+ squaretbl.basePitch = 0.0f;
+ squaretbl.stereo = false;
float v = 0.0f;
for(int i = 0;i < 32;++i)
{
if(i < 15) v = -1.0f; else v = 1.0f;
- squaretbl.WaveData().push_back(v) ;
+ squaretbl.waveData.push_back(v) ;
}
- waveTable_.push_back(squaretbl);
+ WaveTable::WaveTables.push_back(std::move(squaretbl));
}
// \8eO\8ap\94g\83e\81[\83u\83\8b
{
WaveTable tritbl;
- tritbl.SampleRate(440.0f);
- tritbl.BasePitch(1.0f);
- tritbl.Stereo(false);
+ tritbl.sampleRate = 440.0f;
+ tritbl.basePitch = 0.0f;
+ tritbl.stereo = false;
float v = -1.0f,d = 2.0f / 16.0f;
for(int i = 0;i < 32;++i)
{
if(i < 15) d = -d;
- tritbl.WaveData().push_back(v) ;
+ tritbl.waveData.push_back(v) ;
v += d;
}
- waveTable_.push_back(tritbl);
+ WaveTable::WaveTables.push_back(std::move(tritbl));
}
// sin\83e\81[\83u\83\8b
{
WaveTable sintbl;
- sintbl.SampleRate(440.0f);
- sintbl.BasePitch(1.0f);
- sintbl.Stereo(false);
+ sintbl.sampleRate = 440.0f;
+ sintbl.basePitch = 0.0f;
+ sintbl.stereo = false;
float v = 0.0f,d = 2.0f * M_PI / 128.0f;
for(int i = 0;i < 128;++i)
{
- sintbl.WaveData().push_back(sinf(v));
+ sintbl.waveData.push_back(sinf(v));
v += d;
}
- waveTable_.push_back(sintbl);
+ WaveTable::WaveTables.push_back(std::move(sintbl));
}
-
-
-
-
- // ::OutputDebugStringW((boost::wformat(L"waveTable size: %d") % waveTable_[0].WaveData().size()).str().c_str());
-
- // timber\82Ì\83Z\83b\83g\83A\83b\83v
- Timber timber;
- timber.waveTableNo = 3;
- timber.amplitude.gain = 1.0f;
- timber.amplitude.envelope.attackTime = 0.0f;
- timber.amplitude.envelope.decayTime = 0.5f;
- timber.amplitude.envelope.sustainLevel = 0.25f;
- timber.amplitude.envelope.releaseTime = 3.0f;
- timber.amplitude.envelope.gain = 1.0f;
-
- timbers_.push_back(timber);
-
- // Voice\82Ì\83Z\83b\83g\83A\83b\83v
- for(int i = 0; i < 1;++i){
- voices_.push_back(Voice(waveTable_,format.Format.nSamplesPerSec));
- voices_[i].SetTimber(&timbers_[0]);
- voices_[i].NoteOn(1.0f,1.0f);
- }
-
- };
-
- ~impl(){};
-
- void Restart(){};
- void ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
- {
- // \8d¡\82Ì\82Æ\82±\82ë\8fo\97Í\82Í\83X\83e\83\8c\83I\91O\92ñ
- float *ptr = arr.get();
- float buffer[2];
- for(int i = 0;i < bufferSize;++i)
+ // LFO\97p Sin\83e\81[\83u\83\8b
{
- for(int j = 0;j < voices_.size();++j)
+ WaveTable sintbl;
+ sintbl.sampleRate = 440.0f;
+ sintbl.basePitch = 0.0f;
+ sintbl.stereo = false;
+
+ float v = 0.0f,d = 2.0f * M_PI / 128.0f;
+ for(int i = 0;i < 128;++i)
{
- voices_[j].Process(buffer);
- *ptr += buffer[0];
- *(ptr + 1) += buffer[1];
+ sintbl.waveData.push_back(sinf(v) / 2.0f + 0.5f);
+ v += d;
}
- ptr += 2;
+ WaveTable::WaveTables.push_back(std::move(sintbl));
}
- // \83T\83C\83\93\94g\82Ì\90¶\90¬
- //static float sampleIncrement = (440.0f /* Hz */ * (M_PI * 2.0f)) / (float)format_.Format.nSamplesPerSec;
- //static float theta = 0.0f;
- //for (size_t i = 0 ; i < bufferSize ; ++i)
- //{
- // float sinValue = sinf( theta );
- // int offset = i * format_.Format.nChannels;
- // for(size_t j = 0 ;j < format_.Format.nChannels; j++)
- // {
- // arr[offset + j] = sinValue;
- // }
- // theta += sampleIncrement;
- //}
- }
- struct Envelope
- {
- Envelope() :
- attackTime(0.0f),
- decayTime(0.5f),
- sustainLevel(0.5f),
- releaseTime(3.0f),gain(1.0f)
- {}
- float attackTime;
- float decayTime;
- float sustainLevel;
- float releaseTime;
- float gain;
- };
-
- struct Oscillator
- {
- virtual void Process(float * data,float delta) = 0;
- virtual bool Stereo() const = 0;
- };
- struct WaveTable : public Oscillator
- {
- typedef std::vector<float> WaveDataType;
- typedef std::function<void (float * ,float)> ProcessorType;
+ // ::OutputDebugStringW((boost::wformat(L"waveTable size: %d") % osc_[0].WaveData().size()).str().c_str());
- WaveTable() : waveCounter_(0.0f),stereo_(false)
- {
- Stereo(false);
- };
-
- WaveTable(const WaveTable& src) :
- sampleRate_(src.sampleRate_),//
- basePitch_(src.basePitch_),
- waveCounter_(src.waveCounter_),
- waveData_(src.waveData_)
- {
- Stereo(src.stereo_);
+ // timber\82Ì\83Z\83b\83g\83A\83b\83v
+ for(int i = 0; i < channel;++i){
+
+ Timber timber;
+ timber.oscillator.reset(new WaveTableOscillator(&WaveTable::WaveTables.at(0)));
+ timber.amplitude.gain = 1.0f;
+ timber.amplitude.envelope.releaseNoteOff = true;
+ timber.amplitude.envelope.attackTime = 0.01f;
+ timber.amplitude.envelope.decayTime = 0.02f;
+ timber.amplitude.envelope.sustainLevel = 0.5f;
+ timber.amplitude.envelope.releaseTime = 0.2f;
+ timber.amplitude.envelope.gain = 1.0f;
+ timber.amplitude.lfo.waveForm = &(WaveTable::WaveTables[4]);
+ timber.amplitude.lfo.freq = 5.0f;
+ timber.amplitude.lfo.gain = 0.0f;
+
+ timber.pitch.lfo.freq = 10.0f;
+ timber.pitch.lfo.gain = 0.000f;
+ timber.pitch.lfo.waveForm = &(WaveTable::WaveTables[4]);
+ timber.pitch.lfo.startNoteOn = true;
+ timber.pitch.envelope.attackTime = 0.0f;
+ timber.pitch.envelope.decayTime = 0.02f;
+ timber.pitch.envelope.sustainLevel = 0.5f;
+ timber.pitch.envelope.gain =0.0f;
+ timber.pitch.pitch = 0.0f;
+
+ timber.pan.lfo.freq = 2.0f;
+ timber.pan.lfo.gain = 1.0f;
+ timber.pan.lfo.waveForm = &(WaveTable::WaveTables[3]);
+ timber.pan.lfo.startNoteOn = true;
+ timber.pan.envelope.enable = false;
+ timber.pan.lfo.envelope.enable = false;
+ timber.pan.pan = 0.0f;
+
+ timber.filter.lfo.freq = 10.0f;
+ timber.filter.lfo.gain = 1.0f;
+ timber.filter.lfo.waveForm = &(WaveTable::WaveTables[4]);
+ timber.filter.lfo.startNoteOn = true;
+ timber.filter.cutoff = 8000.0f;
+ timber.filter.resonance = 0.5f;
+
+ programs_.push_back(Program(std::move((boost::wformat(L"Program No.%d") % i).str()),std::move(timber)));
+// timbers_.push_back(std::move(timber));
}
- void Process(float * data,float delta)
+ // Voice\82Ì\83Z\83b\83g\83A\83b\83v
+ //Voice v((float)format.Format.nSamplesPerSec);
+ //v.SetProgram(0,programs_[0]);
+ //Voice v1((float)format.Format.nSamplesPerSec);
+ //v1.SetProgram(0,programs_[0]);
+ //Voice v4 = v;
+ //Voice v5 = v;
+ //Voice v2 = std::move(v);
+ //Voice v3(std::move(v1));
+
+ for(int i = 0; i < channel;++i)
{
- processor_(data,delta);
+ voices_.push_back(Voice((float)format.Format.nSamplesPerSec));
}
- bool Stereo() const {return stereo_;}
- void Stereo(bool v) {
- stereo_ = v;
- if(v)
- {
- processor_ = [&](float * data,float delta) -> void
- {
- waveCounter_ += delta;
-
- if(waveData_.size() <= (int)(waveCounter_ * 2.0f))
- {
- waveCounter_ -= (float)waveData_.size() / 2.0f;
- }
-
- int index = (float) waveCounter_;
- float *src = &waveData_[index * 2];
- *data = *src;
- ++data;++src;
- *data = *src;
-
- };
- } else {
- processor_ = [&](float * data,float delta) -> void
- {
- waveCounter_ += delta;
- if(waveData_.size() <= (int)(waveCounter_))
- {
- waveCounter_ -= (float)waveData_.size();
- }
- int index = (int) waveCounter_;
- float d = waveData_[index];
- *data++ = d;
- *data = d;
-
-
- };
- }
- }
- WaveDataType& WaveData() {return waveData_;}
- void WaveData(const WaveDataType& src)
+ for(int i = 0; i < channel;++i)
{
- waveData_ = src;
+ voices_[i].SetProgram(0,programs_[0]);
}
- void SampleRate(float s) {sampleRate_ = s;}
- float SampleRate() const {return sampleRate_;}
- void BasePitch(float v) {basePitch_ = v;}
- float BasePitch() { return basePitch_ ;}
- private:
- bool stereo_;
- float sampleRate_;//
- float basePitch_;
- float waveCounter_;
- ProcessorType processor_;
- WaveDataType waveData_;
- };
-
- struct LFO
- {
- LFO(){}
- WaveTable* waveForm;
- bool startNoteOn;
- float freq;
- float gain;
- };
-
- struct Filter
- {
- int type;
- float level;
- float resonance;
- Envelope envelope;
- LFO lfo;
};
- struct Amplitude
- {
- Amplitude() : gain(1.0f) {}
- float gain;
- Envelope envelope;
- LFO lfo;
- };
-
- struct Pitch {
- Pitch() : pitch(1.0f){}
- float pitch;
- Envelope envelope;
- LFO lfo;
- };
+ ~impl(){};
- struct Pan {
- Pan() : pan(0.5f) {};
- float pan;
- Envelope envelope;
- LFO lfo;
- };
+ void Restart(){};
- struct Timber
+ void Process(float *buffer)
{
- Timber() : waveTableNo(0){};
- int waveTableNo;
- Amplitude amplitude;
- Filter filter;
- Pitch pitch;
- Pan pan;
- };
+ for(int j = 0;j < voices_.size();++j)
+ {
+ voices_[j].Process(buffer);
+ //*buffer += buffer[0];
+ //*(buffer+ 1) += buffer[1];
+ }
+ }
+ //void ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
+ //{
+ // // \8d¡\82Ì\82Æ\82±\82ë\8fo\97Í\82Í\83X\83e\83\8c\83I\91O\92ñ
+ // float *ptr = arr.get();
+ // float buffer[2];
+ // for(int i = 0;i < bufferSize;++i)
+ // {
+ // for(int j = 0;j < voices_.size();++j)
+ // {
+ // voices_[j].Process(buffer);
+ // *ptr += buffer[0];
+ // *(ptr + 1) += buffer[1];
+ // }
+ // ptr += 2;
+ // }
+
+ // //static float sampleIncrement = (440.0f /* Hz */ * (M_PI * 2.0f)) / (float)format_.Format.nSamplesPerSec;
+ // //static float theta = 0.0f;
+
+ // //for (size_t i = 0 ; i < bufferSize ; ++i)
+ // //{
+ // // float sinValue = sinf( theta );
+ // // int offset = i * format_.Format.nChannels;
+ // // for(size_t j = 0 ;j < format_.Format.nChannels; j++)
+ // // {
+ // // arr[offset + j] = sinValue;
+ // // }
+ // // theta += sampleIncrement;
+ // //}
+ //}
- struct Program {
- std::wstring name;
- Timber Timber;
- };
enum struct EnvelopeStatus
{
EnvelopeController() : envelope_(nullptr),stepTime_(1.0f / 44100.0f)
{
}
+ EnvelopeController(const EnvelopeController& src) :
+ envelope_(src.envelope_),
+ status_(src.status_),
+ delta_(src.delta_),
+ counter_(src.counter_),
+ stepTime_(src.stepTime_),
+ time_(src.time_),
+ value_(src.value_)
+ {}
+
+ EnvelopeController(EnvelopeController&& src) :
+ envelope_(std::move( src.envelope_)),
+ status_(std::move(src.status_)),
+ delta_(std::move(src.delta_)),
+ counter_(std::move(src.counter_)),
+ stepTime_(std::move(src.stepTime_)),
+ time_(std::move(src.time_)),
+ value_(std::move(src.value_))
+ {}
+
+ EnvelopeController& operator= (const EnvelopeController& src)
+ {
+ if(this != &src)
+ {
+ envelope_ = src.envelope_;
+ status_ = src.status_;
+ delta_ = src.delta_;
+ counter_ = src.counter_;
+ stepTime_ = src.stepTime_;
+ time_ = src.time_;
+ value_ = src.value_;
+ }
+ return *this;
+ }
+
+ EnvelopeController& operator= (EnvelopeController&& src)
+ {
+ if(this != &src)
+ {
+ envelope_ = std::move(src.envelope_);
+ status_ = std::move(src.status_);
+ delta_ = std::move(src.delta_);
+ counter_ = std::move(src.counter_);
+ stepTime_ = std::move(src.stepTime_);
+ time_ = std::move(src.time_);
+ value_ = std::move(src.value_);
+ }
+ return *this;
+ }
void Reset()
{
envelope_ = env;
stepTime_ = 1.0f / sampleRate;
}
+
void Attack()
{
+ counter_ = 0.0f;
if(envelope_->attackTime == 0.0f)
{
value_ = 1.0f;
void Release()
{
- delta_ = (value_) * stepTime_ / (envelope_->decayTime);
- status_ = EnvelopeStatus::Release;
+ if(envelope_->releaseNoteOff){
+ delta_ = value_ * stepTime_ / (envelope_->releaseTime );
+ status_ = EnvelopeStatus::Release;
+ }
}
float Process()
{
+ if(!IsEnable())
+ {
+ return 1.0f;
+ }
+
+ if(envelope_->gain == 0.0f)
+ {
+ return 0.0f;
+ }
+ counter_ += stepTime_;
switch (status_)
{
case EnvelopeStatus::Attack:
if(value_ <= 0.0f)
{
value_ = 0.0f;
+ status_ = EnvelopeStatus::End;
}
- status_ = EnvelopeStatus::End;
}
break;
}
{
return status_;
}
+
+ bool IsEnable() const {return envelope_ != nullptr && envelope_->enable;}
+
private:
Envelope* envelope_;
EnvelopeStatus status_;
float delta_;
+ float counter_;
float stepTime_;
float time_;
float value_;
struct LFOController
{
- LFOController() : lfo_(nullptr),value_(0.0f),stepTime_(0.0f) {};
- void SetLFO(LFO *lfo)
+ LFOController() : lfo_(nullptr),value_(0.0f),stepTime_(0.0f)
+ {
+ };
+
+ LFOController(const LFOController& src) :
+ lfo_(src.lfo_),
+ osc_(src.osc_),
+ envelopeController_(src.envelopeController_),
+ sampleRate_(src.sampleRate_),
+ value_(src.value_),
+ stepTime_(src.stepTime_),
+ pitchDelta_(src.pitchDelta_),
+ stepDelta_(src.stepDelta_)
+ {
+
+ }
+
+ LFOController(LFOController&& src) :
+ lfo_(std::move(src.lfo_)),
+ osc_(std::move(src.osc_)),
+ envelopeController_(std::move(src.envelopeController_)),
+ sampleRate_(std::move(src.sampleRate_)),
+ value_(std::move(src.value_)),
+ stepTime_(std::move(src.stepTime_)),
+ pitchDelta_(std::move(src.pitchDelta_)),
+ stepDelta_(std::move(src.stepDelta_))
+ {
+
+ }
+
+ LFOController& operator= (const LFOController& src)
+ {
+ if(this != & src)
+ {
+ lfo_ = src.lfo_;
+ osc_ = src.osc_;
+ envelopeController_ = src.envelopeController_;
+ sampleRate_ = src.sampleRate_;
+ value_ = src.value_;
+ stepTime_ = src.stepTime_;
+ pitchDelta_ = src.pitchDelta_;
+ stepDelta_ = src.stepDelta_;
+ }
+ return *this;
+ }
+
+ LFOController& operator= (LFOController&& src)
+ {
+ if(this != & src)
+ {
+ lfo_ = std::move(src.lfo_);
+ osc_ = std::move(src.osc_);
+ envelopeController_ = std::move(src.envelopeController_);
+ sampleRate_ = std::move(src.sampleRate_);
+ value_ = std::move(src.value_);
+ stepTime_ = std::move(src.stepTime_);
+ pitchDelta_ = std::move(src.pitchDelta_);
+ stepDelta_ = std::move(src.stepDelta_);
+ }
+ return *this;
+ }
+
+ void LFOController::LFO(sf::Synthesizer::LFO *lfo)
{
lfo_ = lfo;
}
- void Init()
+
+ sf::Synthesizer::LFO& LFOController::LFO()
{
- assert(lfo_ != nullptr);
+ return *lfo_;
+ }
+
+ void Init(float sampleRate)
+ {
+ // assert(lfo_ != nullptr);
+ osc_.WaveTable(lfo_->waveForm);
+ sampleRate_ = sampleRate;
+ stepDelta_ = 1.0f / sampleRate_;
+ pitchDelta_ = lfo_->freq * ((float)osc_.WaveTable().waveData.size()) / ( sampleRate_ );
+ envelopeController_.Init(&lfo_->envelope,sampleRate);
};
+
+ void Attack()
+ {
+ envelopeController_.Attack();
+ }
+
+ void Release()
+ {
+ envelopeController_.Release();
+ }
+
void Reset()
{
assert(lfo_ != nullptr);
}
- void Process()
+
+ float Process()
{
- assert(lfo_ != nullptr);
+ float buffer[2];
+ osc_.Process(buffer,pitchDelta_,1.0f);
+ float value = buffer[0];
+ value = value * envelopeController_.Process() * lfo_->gain;
+ return value;
};
+
+ void PreProcess()
+ {
+ float buffer[2];
+ osc_.Process(buffer,pitchDelta_,0.0f);
+ envelopeController_.Process();
+ }
+
+ float SampleRate() const {return sampleRate_;}
+ void SampleRate(float v)
+ {
+ sampleRate_ = v;
+ }
+
+// Synthesizer::impl::Envelope& Envelope() {return envelope_;}
+
+
private:
- LFO * lfo_;
+ sf::Synthesizer::LFO * lfo_;
+ WaveTableOscillator osc_;
+// Synthesizer::impl::Envelope envelope_;
EnvelopeController envelopeController_;
+ float sampleRate_;
float value_;
float stepTime_;
+ float pitchDelta_;
+ float stepDelta_;
+ };
+
+ struct FilterController
+ {
+ //sampleRate_,
+ // filter_,
+ // y1_,
+ // y2_,
+ // y3_,
+ // y4_,
+ // oldx_,
+ // oldy1_,
+ // oldy2_,
+ // oldy3_,
+ // x_,
+ // r_,
+ // p_,
+ // k_
+
+ FilterController() :
+ cutoff_(0.0f),
+ sampleRate_(44100.0f),
+ filter_(nullptr),
+ y1_(0.0f),
+ y2_(0.0f),
+ y3_(0.0f),
+ y4_(0.0f),
+ oldx_(0.0f),
+ oldy1_(0.0f),
+ oldy2_(0.0f),
+ oldy3_(0.0f),
+ x_(0.0f),
+ r_(0.0f),
+ p_(0.0f),
+ k_(0.0f)
+ {
+// Init();
+ }
+
+ FilterController(const FilterController& src) :
+ cutoff_(src.cutoff_),
+ sampleRate_(src.sampleRate_),
+ filter_(src.filter_),
+ y1_(src.y1_),
+ y2_(src.y2_),
+ y3_(src.y3_),
+ y4_(src.y4_),
+ oldx_(src.oldx_),
+ oldy1_(src.oldy1_),
+ oldy2_(src.oldy2_),
+ oldy3_(src.oldy3_),
+ x_(src.x_),
+ r_(src.r_),
+ p_(src.p_),
+ k_(src.k_)
+ {
+
+ }
+
+ FilterController(FilterController&& src) :
+ cutoff_(std::move(src.cutoff_)),
+ sampleRate_(std::move(src.sampleRate_)),
+ filter_(std::move(src.filter_)),
+ y1_(std::move(src.y1_)),
+ y2_(std::move(src.y2_)),
+ y3_(std::move(src.y3_)),
+ y4_(std::move(src.y4_)),
+ oldx_(std::move(src.oldx_)),
+ oldy1_(std::move(src.oldy1_)),
+ oldy2_(std::move(src.oldy2_)),
+ oldy3_(std::move(src.oldy3_)),
+ x_(std::move(src.x_)),
+ r_(std::move(src.r_)),
+ p_(std::move(src.p_)),
+ k_(std::move(src.k_))
+ {
+
+ }
+
+ FilterController& operator= (const FilterController& src)
+ {
+ if(this != &src)
+ {
+ cutoff_ = src.cutoff_;
+ sampleRate_ = src.sampleRate_;
+ filter_ = src.filter_;
+ y1_ = src.y1_;
+ y2_ = src.y2_;
+ y3_ = src.y3_;
+ y4_ = src.y4_;
+ oldx_ = src.oldx_;
+ oldy1_ = src.oldy1_;
+ oldy2_ = src.oldy2_;
+ oldy3_ = src.oldy3_;
+ x_ = src.x_;
+ r_ = src.r_;
+ p_ = src.p_;
+ k_ = src.k_;
+ }
+ return *this;
+ }
+
+ FilterController& operator= (FilterController&& src)
+ {
+ if(this != &src)
+ {
+ cutoff_ = std::move(src.cutoff_);
+ sampleRate_ = std::move(src.sampleRate_);
+ filter_ = std::move(src.filter_);
+ y1_ = std::move(src.y1_);
+ y2_ = std::move(src.y2_);
+ y3_ = std::move(src.y3_);
+ y4_ = std::move(src.y4_);
+ oldx_ = std::move(src.oldx_);
+ oldy1_ = std::move(src.oldy1_);
+ oldy2_ = std::move(src.oldy2_);
+ oldy3_ = std::move(src.oldy3_);
+ x_ = std::move(src.x_);
+ r_ = std::move(src.r_);
+ p_ = std::move(src.p_);
+ k_ = std::move(src.k_);
+ }
+ return *this;
+ }
+
+ ~FilterController(){}
+
+ void Init(Synthesizer::Filter* filter,float sampleRate)
+ {
+ filter_ = filter;
+ cutoff_ = filter->cutoff;
+ sampleRate_ = sampleRate;
+ assert(filter_ != nullptr);
+
+ y1_ = y2_ = y3_ = y4_ = oldx_ = oldy1_ = oldy2_ = oldy3_ = 0.0f;
+ Calc();
+ }
+
+ void Calc()
+ {
+ float f = (cutoff_ + cutoff_) / sampleRate_;
+ p_ = f * (1.8f - 0.8f * f);
+ k_ = p_+ p_ - 1.0f;
+
+ float t = (1.0f - p_) * 1.386249f;
+ float t2 = 12.0f + t*t;
+ r_ = filter_->resonance * (t2 + 6.0f * t) / (t2 - 6.0f * t);
+ }
+
+ float Process(float input)
+ {
+ x_ = input - r_ * y4_;
+
+ y1_ = x_ * p_ + oldx_ * p_ - k_ * y1_;
+ y2_ = y1_ * p_ + oldy1_ * p_ - k_ * y2_;
+ y3_ = y2_ * p_ + oldy2_ * p_ - k_ * y3_;
+ y4_ = y3_ * p_ + oldy3_ * p_ - k_ * y4_;
+
+ y4_ -= (y4_ * y4_ * y4_) / 6.0f;
+
+ oldx_ = x_; oldy1_ = y1_; oldy2_ = y2_; oldy3_ = y3_;
+ return y4_;
+ }
+
+ Synthesizer::Filter* FilterController::Filter()
+ {
+ return filter_;
+ }
+
+ void FilterController::Filter(Synthesizer::Filter* filter)
+ {
+ Init(filter,sampleRate_);
+ }
+
+ void Start()
+ {
+ y1_ = y2_ = y3_ = y4_ = oldx_ = oldy1_ = oldy2_ = oldy3_ = 0.0f;
+ Calc();
+ }
+
+ void CutOff(float v ) {cutoff_ = v;Calc();}
+ float CutOff() const {return cutoff_;}
+
+ private:
+ float cutoff_;
+ float sampleRate_;
+ Synthesizer::Filter *filter_;
+ float fs_;
+ float y1_,y2_,y3_,y4_;
+ float oldx_;
+ float oldy1_,oldy2_,oldy3_;
+ float x_;
+ float r_;
+ float p_;
+ float k_;
+
};
+
- typedef std::vector<WaveTable> WaveTablesType;
struct Voice
{
- Voice(WaveTablesType& waveTables,float sampleRate)
+ explicit Voice(float sampleRate)
:
- timber_(nullptr),
- waveTables_(waveTables),
+ programNo_(0),
noteOn_(false),
isFree_(true),
- pitchOffset_(1.0f),
+ pitchOffset_(0.0f),
volumeOffset_(1.0f),
stepTime_(0.0f),
currentTime_(0.0f),
sampleRate_(sampleRate),
pitchDelta_(0.0f),
pitchCounter_(0.0f),
- waveSize_(0),
- waveTable_(nullptr)
+ waveSize_(0)
{};
Voice(const Voice& src)
:
timber_(src.timber_),
- waveTables_(src.waveTables_),
+ programNo_(src.programNo_),
noteOn_(src.noteOn_),
isFree_(src.isFree_),
pitchOffset_(src.pitchOffset_),
pitchDelta_(src.pitchDelta_),
pitchCounter_(src.pitchCounter_),
waveSize_(src.waveSize_),
- waveTable_(src.waveTable_),
- ampEnv(src.ampEnv),
- ampLFO(src.ampLFO),
- filterEnv(src.filterEnv),
- filterLFO(src.filterLFO),
- pitchEnv(src.pitchEnv),
- pitchLFO(src.pitchLFO),
- panEnv(src.panEnv),
- panLFO(src.panLFO)
+ ampEnv_(src.ampEnv_),
+ ampLFO_(src.ampLFO_),
+ filterEnv_(src.filterEnv_),
+ filterLFO_(src.filterLFO_),
+ filterL_(src.filterL_),
+ filterR_(src.filterR_),
+ pitchEnv_(src.pitchEnv_),
+ pitchLFO_(src.pitchLFO_),
+ panEnv_(src.panEnv_),
+ panLFO_(src.panLFO_)
{
+// osc_ = std::move(osc_->Clone());
+ }
+
+ Voice(Voice&& src)
+ :
+ timber_(std::move(src.timber_)),
+ programNo_(std::move(src.programNo_)),
+ noteOn_(std::move(src.noteOn_)),
+ isFree_(std::move(src.isFree_)),
+ pitchOffset_(std::move(src.pitchOffset_)),
+ volumeOffset_(std::move(src.volumeOffset_)),
+ stepTime_(std::move(src.stepTime_)),
+ currentTime_(std::move(src.currentTime_)),
+ curentIndex_(std::move(src.curentIndex_)),
+ pan_(std::move(src.pan_)),
+ sampleRate_(std::move(src.sampleRate_)),
+ pitchDelta_(std::move(src.pitchDelta_)),
+ pitchCounter_(std::move(src.pitchCounter_)),
+ waveSize_(std::move(src.waveSize_)),
+// osc_(std::move(src.osc_)),
+ ampEnv_(std::move(src.ampEnv_)),
+ ampLFO_(std::move(src.ampLFO_)),
+ filterEnv_(std::move(src.filterEnv_)),
+ filterLFO_(std::move(src.filterLFO_)),
+ filterL_(std::move(src.filterL_)),
+ filterR_(std::move(src.filterR_)),
+ pitchEnv_(std::move(src.pitchEnv_)),
+ pitchLFO_(std::move(src.pitchLFO_)),
+ panEnv_(std::move(src.panEnv_)),
+ panLFO_(std::move(src.panLFO_))
+ {
+ // osc_.reset(src.osc_.release());
+ // *this = std::move(src);
+ }
+
+ Voice& operator= (const Voice& src)
+ {
+ if(this != &src)
+ {
+ timber_ = src.timber_;
+ programNo_ = src.programNo_;
+ noteOn_ = src.noteOn_;
+ isFree_ = src.isFree_;
+ pitchOffset_ = src.pitchOffset_;
+ volumeOffset_ = src.volumeOffset_;
+ stepTime_ = src.stepTime_;
+ currentTime_ = src.currentTime_;
+ curentIndex_ = src.curentIndex_;
+ pan_ = src.pan_;
+ sampleRate_ = src.sampleRate_;
+ pitchDelta_ = src.pitchDelta_;
+ pitchCounter_ = src.pitchCounter_;
+ waveSize_ = src.waveSize_;
+ // osc_ = src.osc_->Clone();
+ ampEnv_ = src.ampEnv_;
+ ampLFO_ = src.ampLFO_;
+ filterEnv_ = src.filterEnv_;
+ filterLFO_ = src.filterLFO_;
+ filterL_ = src.filterL_;
+ filterR_ = src.filterR_;
+ pitchEnv_ = src.pitchEnv_;
+ pitchLFO_ = src.pitchLFO_;
+ panEnv_ = src.panEnv_;
+ panLFO_ = src.panLFO_;
+ }
+ return *this;
+ }
+ Voice& operator= (Voice&& src)
+ {
+ if(this != &src)
+ {
+ timber_ = std::move(src.timber_);
+ programNo_ = std::move(src.programNo_);
+ noteOn_ = std::move(src.noteOn_);
+ isFree_ = std::move(src.isFree_);
+ pitchOffset_ = std::move(src.pitchOffset_);
+ volumeOffset_ = std::move(src.volumeOffset_);
+ stepTime_ = std::move(src.stepTime_);
+ currentTime_ = std::move(src.currentTime_);
+ curentIndex_ = std::move(src.curentIndex_);
+ pan_ = std::move(src.pan_);
+ sampleRate_ = std::move(src.sampleRate_);
+ pitchDelta_ = std::move(src.pitchDelta_);
+ pitchCounter_ = std::move(src.pitchCounter_);
+ waveSize_ = std::move(src.waveSize_);
+ // osc_.reset(src.osc_.release());
+ ampEnv_ = std::move(src.ampEnv_);
+ ampLFO_ = std::move(src.ampLFO_);
+ filterEnv_ = std::move(src.filterEnv_);
+ filterLFO_ = std::move(src.filterLFO_);
+ filterL_ = std::move(src.filterL_);
+ filterR_ = std::move(src.filterR_);
+ pitchEnv_ = std::move(src.pitchEnv_);
+ pitchLFO_ = std::move(src.pitchLFO_);
+ panEnv_ = std::move(src.panEnv_);
+ panLFO_ = std::move(src.panLFO_);
+ }
+ return *this;
}
void SetSampleRate(float sampleRate)
sampleRate_ = sampleRate;
}
- void SetTimber(Timber* timber)
+ void SetProgram(int programNo,Program& program)
{
- timber_ = timber;
- waveTable_ = &(waveTables_[timber_->waveTableNo]);
- ampEnv.Init(&(timber_->amplitude.envelope),sampleRate_);
- filterEnv.Init(&(timber_->filter.envelope),sampleRate_);
- pitchEnv.Init(&(timber_->pitch.envelope),sampleRate_);
- panEnv.Init(&(timber_->pitch.envelope),sampleRate_);
+ timber_ = program.timber;
+ programNo_ = programNo;
+ Init();
+// osc_->Init(timber_);
+ }
+
+ void Init()
+ {
+ ampEnv_.Init(&(timber_.amplitude.envelope),sampleRate_);
+ filterEnv_.Init(&(timber_.filter.envelope),sampleRate_);
+ pitchEnv_.Init(&(timber_.pitch.envelope),sampleRate_);
+ panEnv_.Init(&(timber_.pan.envelope),sampleRate_);
+ filterL_.Init(&(timber_.filter),sampleRate_);
+ filterR_.Init(&(timber_.filter),sampleRate_);
+
+ ampLFO_.LFO(&timber_.amplitude.lfo);
+ pitchLFO_.LFO(&timber_.pitch.lfo);
+ panLFO_.LFO(&timber_.pan.lfo);
+ filterLFO_.LFO(&timber_.filter.lfo);
+
+ ampLFO_.Init(sampleRate_);
+ pitchLFO_.Init(sampleRate_);
+ panLFO_.Init(sampleRate_);
+ filterLFO_.Init(sampleRate_);
}
void Process(float* buffer) // 1\83T\83\93\83v\83\8b\95ª\82Ì\8f\88\97\9d\82ð\8ds\82¤
{
- // assert(!isFree_);
+ if(!isFree_){
- //currentTime_ += stepTime_;
+ //if(pitchCounter_ >= (waveSize_ - 1.0f))
+ //{
+ // pitchCounter_ -= (waveSize_ - 1.0f);
+ //}
- //pitchCounter_ += pitchDelta_ * pitchOffset_ * waveTable_->BasePitch() * pitchEnv.Process() * timber_->pitch.pitch;
+ float waveData[2];
- //if(pitchCounter_ >= (waveSize_ - 1.0f))
- //{
- // pitchCounter_ -= (waveSize_ - 1.0f);
- //}
+ timber_.oscillator->Process(
+ waveData,
+ pitchDelta_,
+ pitchOffset_
+ + pitchLFO_.Process()
+ + pitchEnv_.Process()
+ + timber_.pitch.pitch );
- float waveData[2];
+ float cutoff = timber_.filter.cutoff;// + filterEnv_.Process(),
+ filterL_.CutOff(cutoff);
+ filterR_.CutOff(cutoff);
- waveTable_->Process(waveData,pitchDelta_ * pitchOffset_ * waveTable_->BasePitch() * pitchEnv.Process() * timber_->pitch.pitch );
+ waveData[0] = filterL_.Process(waveData[0]);
+ waveData[1] = filterR_.Process(waveData[1]);
- float volume = ampEnv.Process();
- if(volume > 1.0f)
- {
- volume = 1.0f;
- }
- waveData[0] = waveData[0] * volume * volumeOffset_;
- waveData[1] = waveData[1] * volume * volumeOffset_;
+ float volume = ampEnv_.Process() + ampLFO_.Process();
+ if(volume > 1.0f)
+ {
+ volume = 1.0f;
+ }
- // \83N\83\8a\83b\83s\83\93\83O
- //if(waveData > 1.0f) waveData = 1.0f;
- //if(waveData < 1.0f) waveData = -1.0f;
- buffer[0] = waveData[0]; //* pan_;
- buffer[1] = waveData[1]; //* (1.0f - pan_);
- if(!noteOn_ && ampEnv.GetStatus() == EnvelopeStatus::End)
- {
- isFree_ = true;
+ // \83N\83\8a\83b\83s\83\93\83O
+
+ //if(waveData > 1.0f) waveData = 1.0f;
+ //if(waveData < 1.0f) waveData = -1.0f;
+
+ float pan = (pan_ + panLFO_.Process());
+ if(pan > 1.0f) pan = 1.0f;
+ if(pan < -1.0f) pan = -1.0f;
+
+ float rvolume;
+ float lvolume;
+
+
+ if(pan > 0.0f)
+ {
+ rvolume = volume * volumeOffset_;
+ lvolume = rvolume * (1.0f - pan);
+ } else {
+ lvolume = volume * volumeOffset_;
+ rvolume = lvolume * (1.0f + pan);
+ }
+
+ waveData[0] = waveData[0] * lvolume;
+ waveData[1] = waveData[1] * rvolume;
+
+ buffer[0] += waveData[0]; //* pan_;
+ buffer[1] += waveData[1]; //* (1.0f - pan_);
+
+ if(!noteOn_ && ampEnv_.GetStatus() == EnvelopeStatus::End)
+ {
+ isFree_ = true;
+ }
}
}
void NoteOn(float pitch,float volume)
{
if(!noteOn_){
+ isFree_ = false;
noteOn_ = true;
pitchOffset_ = pitch;
volumeOffset_ = volume;
stepTime_ = 1.0f / sampleRate_;
- pitchDelta_ = waveTable_->SampleRate() * ((float)waveTable_->WaveData().size()) / sampleRate_ ;
- // waveSize_ = (float)waveTable_->waveData.size();
+ pitchDelta_ = timber_.oscillator->CalcPitchDelta(sampleRate_);
+ // waveSize_ = (float)osc_->waveData.size();
currentTime_ = 0.0f;
curentIndex_ = 0;
- pan_ = timber_->pan.pan;
+ pan_ = timber_.pan.pan;
pitchCounter_ = 0.0f;
- ampEnv.Attack();
- filterEnv.Attack();
- pitchEnv.Attack();
- panEnv.Attack();
+ ampEnv_.Attack();
+ filterEnv_.Attack();
+ pitchEnv_.Attack();
+ panEnv_.Attack();
+
+ ampLFO_.Attack();
+ filterLFO_.Attack();
+ pitchLFO_.Attack();
+ panLFO_.Attack();
+
+ filterL_.Start();
+ filterR_.Start();
}
}
if(noteOn_)
{
noteOn_ = false;
- ampEnv.Release();
- filterEnv.Release();
- pitchEnv.Release();
- panEnv.Release();
+ ampEnv_.Release();
+ filterEnv_.Release();
+ pitchEnv_.Release();
+ panEnv_.Release();
+
+ ampLFO_.Release();
+ filterLFO_.Release();
+ pitchLFO_.Release();
+ panLFO_.Release();
+
}
}
+ int CurrentProgramNo() const {return programNo_;}
+
private:
- Timber* timber_;
- WaveTablesType& waveTables_;
+ Timber timber_;
+ int programNo_;
bool noteOn_;
bool isFree_;
float pitchOffset_;
float pitchDelta_;
float pitchCounter_;
float waveSize_;
- WaveTable *waveTable_;
- EnvelopeController ampEnv;
- LFOController ampLFO;
- EnvelopeController filterEnv;
- LFOController filterLFO;
- EnvelopeController pitchEnv;
- LFOController pitchLFO;
- EnvelopeController panEnv;
- LFOController panLFO;
+ // std::unique_ptr<Oscillator> osc_;
+ EnvelopeController ampEnv_;
+ LFOController ampLFO_;
+ EnvelopeController filterEnv_;
+ LFOController filterLFO_;
+ FilterController filterL_;
+ FilterController filterR_;
+ EnvelopeController pitchEnv_;
+ LFOController pitchLFO_;
+ EnvelopeController panEnv_;
+ LFOController panLFO_;
};
typedef std::vector<Voice> VoicesType;
typedef std::vector<Timber> TimbersType;
typedef std::vector<Program> ProgramsType;
+ void NoteOn(int index,float pitch,float velocity)
+ {
+ voices_[index].NoteOn(pitch,velocity);
+ };
+
+ void NoteOff(int index)
+ {
+ voices_[index].NoteOff();
+ };
+
+ void AddProgram(Program&& program)
+ {
+ programs_.push_back(program);
+ }
+
+ Program& GetProgram(int index)
+ {
+ return programs_.at(index);
+ }
+
+ void UpdateProgram(int index,Program&& program)
+ {
+ programs_[index] = std::move(program);
+ }
+
+ size_t ProgramsSize()
+ {
+ return programs_.size();
+ }
+
+ void AssignProgramToVoice(int programNo,int voiceChannelNo)
+ {
+ assert(programNo < programs_.size() && voiceChannelNo < voices_.size());
+ voices_.at(voiceChannelNo).SetProgram(programNo,programs_.at(programNo));
+ }
+
+ size_t Voices() const {return voices_.size();};
+
private:
WAVEFORMATEXTENSIBLE format_;
ProgramsType programs_;// \83v\83\8a\83Z\83b\83g
- TimbersType timbers_;
VoicesType voices_; // Max 64 Voices
- WaveTablesType waveTable_;
+// WaveTablesType waveTables_;
};
- WaveTableSynth::WaveTableSynth() : impl_(new WaveTableSynth::impl()){};
+ Synthesizer::Synthesizer() : impl_(new Synthesizer::impl()){};
- WaveTableSynth::WaveTableSynth(WAVEFORMATEXTENSIBLE& format ) : impl_(new WaveTableSynth::impl(format))
+ Synthesizer::Synthesizer(WAVEFORMATEXTENSIBLE& format,int channel ) : impl_(new Synthesizer::impl(format,channel))
{
}
- WaveTableSynth::~WaveTableSynth()
+ Synthesizer::~Synthesizer()
{
}
- void WaveTableSynth::ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
+ //void Synthesizer::ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
+ //{
+ // impl_->ProcessBuffer(arr,bufferSize);
+ //}
+
+ void Synthesizer::Process(float* buffer)
{
- impl_->ProcessBuffer(arr,bufferSize);
+ impl_->Process(buffer);
}
- void WaveTableSynth::Restart()
+
+ void Synthesizer::Restart()
{
impl_->Restart();
}
+
+ void Synthesizer::NoteOn(int index,float pitch,float velocity)
+ {
+ impl_->NoteOn(index,pitch,velocity);
+ };
+ void Synthesizer::NoteOff(int index)
+ {
+ impl_->NoteOff(index);
+ };
+
+ size_t Synthesizer::Voices() const
+ {
+ return impl_->Voices();
+ }
+
+ void Synthesizer::AddProgram(Program&& program)
+ {
+ impl_->AddProgram(std::move(program));
+ }
+
+ Synthesizer::Program& Synthesizer::GetProgram(int index)
+ {
+ return impl_->GetProgram(index);
+ };
+
+ void Synthesizer::UpdateProgram(int index,Program&& program)
+ {
+ impl_->UpdateProgram(index,std::move(program));
+ }
+ size_t Synthesizer::ProgramsSize()
+ {
+ return impl_->ProgramsSize();
+ }
+
+ void Synthesizer::AssignProgramToVoice(int programNo,int voiceChannelNo)
+ {
+ impl_->AssignProgramToVoice(programNo,voiceChannelNo);
+ }
+
}
#pragma once
namespace sf {
- struct WaveTableSynth
+ struct Synthesizer
{
- WaveTableSynth();
- explicit WaveTableSynth(WAVEFORMATEXTENSIBLE& format);
- ~WaveTableSynth();
+ // \83G\83\93\83x\83\8d\81[\83v\83p\83\89\83\81\81[\83^
+ struct Envelope
+ {
+ Envelope() :
+ enable(true),
+ releaseNoteOff(true),
+ attackTime(0.0f),
+ decayTime(0.5f),
+ sustainLevel(0.5f),
+ releaseTime(3.0f),
+ gain(1.0f)
+ {}
+
+ Envelope(const Envelope& src) :
+ enable(src.enable),
+ releaseNoteOff(src.releaseNoteOff),
+ attackTime(src.attackTime),
+ decayTime(src.decayTime),
+ sustainLevel(src.sustainLevel),
+ releaseTime(src.releaseTime),
+ gain(src.gain)
+ {}
+
+ Envelope(Envelope&& src) :
+ enable(std::move(src.enable)),
+ releaseNoteOff(std::move(src.releaseNoteOff)),
+ attackTime(std::move(src.attackTime)),
+ decayTime(std::move(src.decayTime)),
+ sustainLevel(std::move(src.sustainLevel)),
+ releaseTime(std::move(src.releaseTime)),
+ gain(std::move(src.gain))
+ {}
+
+ Envelope& operator=(const Envelope& src)
+ {
+ if(this != &src)
+ {
+ enable = src.enable;
+ releaseNoteOff = src.releaseNoteOff;
+ attackTime = src.attackTime;
+ decayTime = src.decayTime;
+ sustainLevel = src.sustainLevel;
+ releaseTime = src.releaseTime;
+ gain = src.gain;
+ }
+ return *this;
+ }
+
+ Envelope& operator=(Envelope&& src)
+ {
+ if(this != &src)
+ {
+ enable = std::move(src.enable);
+ releaseNoteOff = std::move(src.releaseNoteOff);
+ attackTime = std::move(src.attackTime);
+ decayTime = std::move(src.decayTime);
+ sustainLevel = std::move(src.sustainLevel);
+ releaseTime = std::move(src.releaseTime);
+ gain = std::move(src.gain);
+ }
+ return *this;
+ }
+
+ bool enable;
+ bool releaseNoteOff;
+ float attackTime;
+ float decayTime;
+ float sustainLevel;
+ float releaseTime;
+ float gain;
+ };
+
+ struct Timber;
+ enum struct OscillatorCategory
+ {
+ WaveTable,SquwareWave,SinWave
+ };
+ // \83I\83V\83\8c\81[\83^\83C\83\93\83^\81[\83t\83F\81[\83X
+ struct Oscillator
+ {
+ typedef std::unique_ptr<Oscillator> PtrType;
+ virtual ~Oscillator(){}
+ virtual void Process(float * data,float delta,float offset) = 0;
+ virtual float SampleRate() const = 0;
+ virtual float CalcPitchDelta(float sampleRate) = 0;
+// virtual void Init(Timber& timber) = 0;
+ virtual OscillatorCategory Category() = 0;
+ virtual PtrType Clone() = 0;
+ };
+
+ // \83E\83F\81[\83u\83f\81[\83^
+ typedef std::vector<float> WaveData;
+
+ // \83E\83F\81[\83u\83e\81[\83u\83\8b
+ struct WaveTable
+ {
+ WaveTable() :
+ stereo(false),
+ sampleRate(44100.0f),//
+ basePitch(0.0f)
+ {};
+
+ WaveTable(const WaveTable& src) :
+ stereo(src.stereo),
+ sampleRate(src.sampleRate),//
+ basePitch(src.basePitch)
+ {waveData = src.waveData;};
+
+ WaveTable(WaveTable&& src) :
+ stereo(std::move(src.stereo)),
+ sampleRate(std::move(src.sampleRate)),//
+ basePitch(std::move(src.basePitch))
+ {waveData = std::move(src.waveData);};
+
+ WaveTable& operator=(const WaveTable& src)
+ {
+ if(this != &src)
+ {
+ stereo = src.stereo;
+ sampleRate = src.sampleRate;//
+ basePitch = src.basePitch;
+ waveData = src.waveData;
+ }
+ return *this;
+ }
+
+ WaveTable& operator=(WaveTable&& src)
+ {
+ if(this != &src)
+ {
+ stereo = std::move(src.stereo);
+ sampleRate = std::move(src.sampleRate);//
+ basePitch = std::move(src.basePitch);
+ waveData = std::move(src.waveData);
+ }
+ return *this;
+ }
+
+ bool stereo;
+ float sampleRate;//
+ float basePitch;
+ WaveData waveData;
+ static std::vector<WaveTable> WaveTables;
+ };
+
+ // LFO
+ struct LFO
+ {
+ LFO() :
+ waveForm(nullptr),
+ startNoteOn(true),
+ freq(20.0f),
+ gain(1.0f)
+ {}
+ LFO(const LFO &src)
+ :
+ waveForm(src.waveForm),
+ envelope(src.envelope),
+ startNoteOn(src.startNoteOn),
+ freq(src.freq),
+ gain(src.gain)
+ {}
+
+ LFO(LFO &&src) :
+ waveForm(std::move(src.waveForm)),
+ envelope(std::move(src.envelope)),
+ startNoteOn(std::move(src.startNoteOn)),
+ freq(std::move(src.freq)),
+ gain(std::move(src.gain))
+ {}
+
+ LFO& operator=(const LFO &src)
+ {
+ if(this != &src)
+ {
+ waveForm = src.waveForm;
+ envelope = src.envelope;
+ startNoteOn = src.startNoteOn;
+ freq = src.freq;
+ gain = src.gain;
+
+ }
+ return *this;
+ }
+ LFO& operator=(LFO &&src)
+ {
+ if(this != &src)
+ {
+ waveForm = std::move(src.waveForm);
+ envelope = std::move(src.envelope);
+ startNoteOn = std::move(src.startNoteOn);
+ freq = std::move(src.freq);
+ gain = std::move(src.gain);
+
+ }
+ return *this;
+ }
+
+ bool startNoteOn;
+ WaveTable* waveForm;
+ Envelope envelope;
+ float freq;
+ float gain;
+ };
+
+ // \83t\83B\83\8b\83^\81[\83J\83e\83S\83\8a\81[
+ enum struct FilterCategory
+ {
+ LPF,HPF,BPF
+ };
+
+ // \83t\83B\83\8b\83^\81[
+ struct Filter
+ {
+ Filter() : category(FilterCategory::LPF),level(0.0f),resonance(0.0f),cutoff(0.0f){};
+ Filter(const Filter& src) :
+ category(src.category),
+ level(src.level),
+ cutoff(src.cutoff),
+ resonance(src.resonance),
+ envelope(src.envelope),
+ lfo(src.lfo)
+ {
+ }
+
+ Filter( Filter&& src) :
+ category(std::move(src.category)),
+ level(std::move(src.level)),
+ cutoff(std::move(src.cutoff)),
+ resonance(std::move(src.resonance)),
+ envelope(std::move(src.envelope)),
+ lfo(std::move(src.lfo))
+ {
+ }
+
+ Filter& operator= (const Filter& src)
+ {
+ if(this != &src)
+ {
+ category = src.category;
+ level = src.level;
+ cutoff = src.cutoff;
+ resonance = src.resonance;
+ envelope = src.envelope;
+ lfo = src.lfo;
+ }
+ return *this;
+ }
+
+ Filter& operator= (Filter&& src)
+ {
+ if(this != &src)
+ {
+ category = std::move(src.category);
+ level = std::move(src.level);
+ cutoff = std::move(src.cutoff);
+ resonance = std::move(src.resonance);
+ envelope = std::move(src.envelope);
+ lfo = std::move(src.lfo);
+ }
+ return *this;
+ }
+
+ FilterCategory category;
+ float level;
+ float cutoff;
+ float resonance;
+ Envelope envelope;
+ LFO lfo;
+ };
+
+ // \89¹\97Ê\83p\83\89\83\81\81[\83^
+ struct Amplitude
+ {
+ Amplitude() : gain(1.0f) {}
+ Amplitude(const Amplitude& src) :
+ gain(src.gain),
+ envelope(src.envelope),
+ lfo(src.lfo)
+ {}
+
+ Amplitude(Amplitude&& src) :
+ gain(std::move(src.gain)),
+ envelope(std::move(src.envelope)),
+ lfo(std::move(src.lfo))
+ {}
+ Amplitude& operator= (const Amplitude& src)
+ {
+ if(this != &src)
+ {
+ gain = src.gain;
+ envelope = src.envelope;
+ lfo = src.lfo;
+ }
+ return *this;
+ }
+
+ Amplitude& operator= (Amplitude&& src)
+ {
+ if(this != &src)
+ {
+ gain = std::move(src.gain);
+ envelope = std::move(src.envelope);
+ lfo = std::move(src.lfo);
+ }
+ return *this;
+ }
+
+ float gain;
+ Envelope envelope;
+ LFO lfo;
+ };
+
+ // \8eü\94g\90\94\83p\83\89\83\81\81[\83^
+ struct Pitch {
+ Pitch() : pitch(1.0f){}
+ Pitch(const Pitch& src) :
+ pitch(src.pitch),
+ envelope(src.envelope),
+ lfo(src.lfo)
+ {}
+
+ Pitch(Pitch&& src) :
+ pitch(std::move(src.pitch)),
+ envelope(std::move(src.envelope)),
+ lfo(std::move(src.lfo))
+ {}
+ Pitch& operator= (const Pitch& src)
+ {
+ if(this != &src)
+ {
+ pitch = src.pitch;
+ envelope = src.envelope;
+ lfo = src.lfo;
+ }
+ return *this;
+ }
+
+ Pitch& operator= (Pitch&& src)
+ {
+ if(this != &src)
+ {
+ pitch = std::move(src.pitch);
+ envelope = std::move(src.envelope);
+ lfo = std::move(src.lfo);
+ }
+ return *this;
+ }
+
+ float pitch;
+ Envelope envelope;
+ LFO lfo;
+ };
+
+ // \92è\88Ê\83p\83\89\83\81\81[\83^
+ struct Pan {
+ Pan() : pan(0.5f) {};
+ Pan(const Pan& src) :
+ pan(src.pan),
+ envelope(src.envelope),
+ lfo(src.lfo)
+ {}
+
+ Pan(Pan&& src) :
+ pan(std::move(src.pan)),
+ envelope(std::move(src.envelope)),
+ lfo(std::move(src.lfo))
+ {}
+
+ Pan& operator= (const Pan& src)
+ {
+ if(this != &src)
+ {
+ pan = src.pan;
+ envelope = src.envelope;
+ lfo = src.lfo;
+
+ }
+ return *this;
+ }
+
+ Pan& operator= (Pan&& src)
+ {
+ if(this != &src)
+ {
+ pan = std::move(src.pan);
+ envelope = std::move(src.envelope);
+ lfo = std::move(src.lfo);
+ }
+ return *this;
+ }
+
+ float pan;
+ Envelope envelope;
+ LFO lfo;
+ };
+
+ typedef std::vector<WaveTable> WaveTablesType;
+
+ struct WaveTableOscillator : public Oscillator
+ {
+ typedef std::function<void (float * ,float,float)> ProcessorType;
+
+ WaveTableOscillator() : waveTable_(nullptr),waveCounter_(0.0f)
+ {
+
+ };
+
+ explicit WaveTableOscillator(WaveTable* waveTable) : waveTable_(nullptr),waveCounter_(0.0f)
+ {
+ WaveTable(waveTable);
+ }
+
+ WaveTableOscillator(const WaveTableOscillator& src) : waveTable_(nullptr),
+ waveCounter_(src.waveCounter_)
+ {
+ if(src.waveTable_ != nullptr)
+ {
+ WaveTable(src.waveTable_);
+ }
+
+ }
+
+ WaveTableOscillator(WaveTableOscillator&& src) :
+ waveTable_(std::move(nullptr)),
+ waveCounter_(std::move(src.waveCounter_))
+ {
+ if(src.waveTable_ != nullptr)
+ {
+ WaveTable(src.waveTable_);
+ }
+
+ }
+
+ WaveTableOscillator& operator= (const WaveTableOscillator& src)
+ {
+ if(this != &src)
+ {
+ this->waveCounter_ = src.waveCounter_;
+ WaveTable(src.waveTable_);
+ }
+ return *this;
+ }
+
+ WaveTableOscillator& operator= (WaveTableOscillator&& src)
+ {
+ if(this != &src)
+ {
+ this->waveCounter_ = std::move(src.waveCounter_);
+ WaveTable(src.waveTable_);
+ }
+ return *this;
+ }
+
+ void Process(float * data,float delta,float offset)
+ {
+
+ //if(waveTable_->stereo)
+ //{
+ // ProcessStereo(data,delta);
+ //} else {
+ // ProcessMono(data,delta);
+ //}
+ processor_(data,delta,offset);
+ }
+
+ void ProcessStereo(float * data,float delta,float offset)
+ {
+ waveCounter_ += delta * (offset + waveTable_->basePitch);
+
+ if(waveTable_->waveData.size() <= (int)(waveCounter_ * 2.0f))
+ {
+ waveCounter_ -= (float)waveTable_->waveData.size() / 2.0f;
+ }
+
+ int index = (float) waveCounter_;
+ float *src = &waveTable_->waveData[index * 2];
+ *data = *src;
+ ++data;++src;
+ *data = *src;
+
+ }
+
+ void ProcessMono(float * data,float delta,float offset)
+ {
+ waveCounter_ += delta * (offset + waveTable_->basePitch);
+
+ if(waveTable_->waveData.size() <= (int)(waveCounter_))
+ {
+ waveCounter_ -= (float)waveTable_->waveData.size();
+ }
+ int index = (int) waveCounter_;
+ float d = waveTable_->waveData[index];
+ *data++ = d;
+ *data = d;
+
+ }
+
+ float SampleRate() const {return waveTable_->sampleRate;}
+ float CalcPitchDelta(float sampleRate)
+ {
+ return SampleRate() * ((float)WaveTable().waveData.size() / sampleRate);
+ }
+
+ //void Init()
+ //{
+ // //WaveTable(&(WaveTable::WaveTables[timber.waveTableNo]));
+ //}
+
+ OscillatorCategory Category() {return OscillatorCategory::WaveTable;};
+
+ PtrType Clone() {return PtrType(new WaveTableOscillator(*this));}
+
+ Synthesizer::WaveTable& WaveTableOscillator::WaveTable() {return *waveTable_;}
+ void Synthesizer::WaveTableOscillator::WaveTable(Synthesizer::WaveTable *p);
+
+ private:
+ Synthesizer::WaveTable *waveTable_;
+ float waveCounter_;
+ ProcessorType processor_;
+ };
+
+ // \89¹\90F\83p\83\89\83\81\81[\83^
+ struct Timber
+ {
+ Timber() {};
+ Timber(const Timber& src) :
+ amplitude(src.amplitude),
+ filter(src.filter),
+ pitch(src.pitch),
+ pan(src.pan)
+ {
+ if(src.oscillator.get() != nullptr){
+ oscillator = src.oscillator->Clone();
+ }
+ }
+
+ Timber(Timber&& src) :
+// waveTableNo(std::move(src.waveTableNo)),
+ amplitude(std::move(src.amplitude)),
+ filter(std::move(src.filter)),
+ pitch(std::move(src.pitch)),
+ pan(std::move(src.pan))
+ {
+ if(src.oscillator.get() != nullptr){
+ oscillator.reset(src.oscillator.release());
+ }
+ }
+
+ Timber& operator= (const Timber& src)
+ {
+ if(this != &src)
+ {
+ // waveTableNo = src.waveTableNo;
+ if(src.oscillator.get() != nullptr){
+ oscillator = src.oscillator->Clone();
+ }
+ amplitude = src.amplitude;
+ filter = src.filter;
+ pitch = src.pitch;
+ pan = src.pan;
+
+ }
+ return *this;
+ }
+
+ Timber& operator= (Timber&& src)
+ {
+ if(this != &src)
+ {
+ // waveTableNo = std::move(src.waveTableNo);
+ if(src.oscillator.get() != nullptr){
+ oscillator.reset(src.oscillator.release());
+ }
+ amplitude = std::move(src.amplitude);
+ filter = std::move(src.filter);
+ pitch = std::move(src.pitch);
+ pan = std::move(src.pan);
+ }
+ return *this;
+ }
+
+ Oscillator::PtrType oscillator;
+// int waveTableNo;
+ Amplitude amplitude;
+ Filter filter;
+ Pitch pitch;
+ Pan pan;
+ };
+
+ // \89¹\90F\83v\83\8d\83O\83\89\83\80\83p\83\89\83\81\81[\83^
+ struct Program {
+ Program(){}
+ Program(const std::wstring& name,const Timber& timber) :
+ name(name),timber(timber)
+ {}
+
+ Program(const Program& src)
+ :
+ name(src.name),timber(src.timber)
+ {
+
+ }
+
+ Program(const Program&& src) :
+ name(std::move(src.name)),timber(std::move(src.timber))
+ {
+
+ }
+
+ Program& operator= (const Program& src)
+ {
+ if(this != &src)
+ {
+ name = src.name;
+ timber = src.timber;
+ }
+ return *this;
+ }
+
+ Program& operator= (const Program&& src)
+ {
+ if(this != &src)
+ {
+ name = std::move(src.name);
+ timber = std::move(src.timber);
+ }
+ return *this;
+ }
+
+ std::wstring name;
+ Timber timber;
+ };
+ typedef std::vector<Program> ProgramsType;
+ // \83R\83\93\83X\83g\83\89\83N\83^
+ Synthesizer();
+ // \83R\83\93\83X\83g\83\89\83N\83^
+ explicit Synthesizer(WAVEFORMATEXTENSIBLE& format,int channel = 4);
+ // \83f\83X\83g\83\89\83N\83^
+ ~Synthesizer();
+ // \83\8a\83X\83^\81[\83g
void Restart();
- void ProcessBuffer(boost::shared_array<float> arr,int bufferSize);
+ // \94g\8c`\90¶\90¬\8f\88\97\9d
+ void Process(float* buffer);
+ // \83m\81[\83g\83I\83\93\8f\88\97\9d
+ void NoteOn(int index,float pitch,float velocity);
+ // \83m\81[\83g\83I\83t\8f\88\97\9d
+ void NoteOff(int index);
+
+ // \89¹\90F\83v\83\8d\83O\83\89\83\80
+ void AddProgram(Program&& program);
+ Program& GetProgram(int index);
+ void UpdateProgram(int index,Program&& Program);
+ size_t ProgramsSize();
+ void AssignProgramToVoice(int programNo,int voiceChannelNo);
+
+ size_t Voices() const;
+
private:
struct impl;
std::unique_ptr<impl> impl_;