--- /dev/null
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2012 for Windows 8
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SynthApp", "SynthApp\SynthApp.vcxproj", "{823BBD24-B801-49EE-9763-F8186C389F34}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|ARM = Release|ARM
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|ARM.ActiveCfg = Debug|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|ARM.Build.0 = Debug|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|ARM.Deploy.0 = Debug|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|Win32.ActiveCfg = Debug|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|Win32.Build.0 = Debug|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|Win32.Deploy.0 = Debug|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|x64.ActiveCfg = Debug|x64
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|x64.Build.0 = Debug|x64
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Debug|x64.Deploy.0 = Debug|x64
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|ARM.ActiveCfg = Release|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|ARM.Build.0 = Release|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|ARM.Deploy.0 = Release|ARM
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|Win32.ActiveCfg = Release|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|Win32.Build.0 = Release|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|Win32.Deploy.0 = Release|Win32
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|x64.ActiveCfg = Release|x64
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|x64.Build.0 = Release|x64
+ {823BBD24-B801-49EE-9763-F8186C389F34}.Release|x64.Deploy.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
--- /dev/null
+<Application
+ x:Class="SynthApp.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:SynthApp">
+
+ <Application.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+
+ <!--
+ Styles that define common aspects of the platform look and feel
+ Required by Visual Studio project and item templates
+ -->
+ <ResourceDictionary Source="Common/StandardStyles.xaml"/>
+ </ResourceDictionary.MergedDictionaries>
+
+ </ResourceDictionary>
+ </Application.Resources>
+</Application>
--- /dev/null
+//
+// App.xaml.cpp
+// App クラスの実装。
+//
+
+#include "pch.h"
+#include "App.xaml.h"
+#include "MainPage.xaml.h"
+#include "BasicMath.h"
+
+using namespace SynthApp;
+
+using namespace Platform;
+using namespace Windows::ApplicationModel;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Interop;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace concurrency;
+using namespace DirectX;
+
+
+// 空のアプリケーション テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234227 を参照してください
+
+/// <summary>
+/// 単一アプリケーション オブジェクトを初期化します。これは、実行される作成したコードの
+/// 最初の行であり、main() または WinMain() と論理的に等価です。
+/// </summary>
+App::App() : soundStopped_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)),isDestroy_(true)
+{
+ InitializeComponent();
+ Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
+}
+
+App::~App()
+{
+ if(!isDestroy_)
+ {
+ StopSound();
+ }
+
+}
+/// <summary>
+/// アプリケーションがエンド ユーザーによって正常に起動されたときに呼び出されます。他のエントリ ポイントは、
+/// アプリケーションが特定のファイルを開くために呼び出されたときに
+/// 検索結果やその他の情報を表示するために使用されます。
+/// </summary>
+/// <param name="pArgs">Details about the launch request and process.</param>
+void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ pArgs)
+{
+ // Do not repeat app initialization when already running, just ensure that
+ // the window is active
+ if (pArgs->PreviousExecutionState == ApplicationExecutionState::Running)
+ {
+ Window::Current->Activate();
+ return;
+ }
+
+ soundDriver_.reset(new sf::SoundDriver());
+ soundManager_.reset(new sf::SoundManager(*soundDriver_.get()));
+ InitSound();
+
+ if (pArgs->PreviousExecutionState == ApplicationExecutionState::Terminated)
+ {
+ //TODO: 以前中断したアプリケーションから状態を読み込みます。
+ }
+
+ // ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
+ auto rootFrame = ref new Frame();
+ if (!rootFrame->Navigate(TypeName(MainPage::typeid)))
+ {
+ throw ref new FailureException("Failed to create initial page");
+ }
+
+ // フレームを現在のウィンドウに配置し、アクティブであることを確認します
+ Window::Current->Content = rootFrame;
+ Window::Current->Activate();
+
+ StartSound();
+
+}
+
+/// <summary>
+/// アプリケーションの実行が中断されたときに呼び出されます。アプリケーションの状態は、
+/// アプリケーションが終了されるのか、メモリの内容がそのままで再開されるのか
+/// わからない状態で保存されます。
+/// </summary>
+/// <param name="sender">中断要求の送信元。</param>
+/// <param name="e">中断要求の詳細。</param>
+void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
+{
+ (void) sender; // Unused parameter
+ (void) e; // Unused parameter
+
+ //TODO: アプリケーションの状態を保存してバックグラウンドの動作があれば停止します
+}
+
+void App::InitSound()
+{
+ sf::SoundManager& sm(*soundManager_.get());
+ sm.Synthesizer().isEnable(false);
+ sm.Synthesizer().Clear();
+ // sm.Synthesizer().WaveTables().clear();
+
+ // 鋸波テーブルを作る
+ {
+ sf::Synthesizer::WaveTable sawtbl;
+ sawtbl.sampleRate = 440.0f;
+ sawtbl.basePitch = 0.0f;
+ sawtbl.stereo = false;
+
+ float v = -1.0f,d = 2.0f / 1024.0f;
+ for(int i = 0;i < 1024;++i)
+ {
+ // if(i < 15) v = -1.0f; else v = 1.0f;
+ sawtbl.waveData.push_back(v) ;
+ v += d;
+ }
+ sm.Synthesizer().WaveTables().push_back(std::move(sawtbl));
+ }
+
+ // 矩形波テーブルを作る
+ {
+ sf::Synthesizer::WaveTable squaretbl;
+ 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) ;
+ }
+ sm.Synthesizer().WaveTables().push_back(std::move(squaretbl));
+ }
+
+ // 三角波テーブル
+ {
+ sf::Synthesizer::WaveTable tritbl;
+ 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) ;
+ v += d;
+ }
+ sm.Synthesizer().WaveTables().push_back(std::move(tritbl));
+ }
+
+ // sinテーブル
+ {
+ sf::Synthesizer::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)
+ {
+ sintbl.waveData.push_back(sinf(v));
+ v += d;
+ }
+ sm.Synthesizer().WaveTables().push_back(std::move(sintbl));
+ }
+
+ // LFO用 Sinテーブル
+ {
+ sf::Synthesizer::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)
+ {
+ sintbl.waveData.push_back(sinf(v) / 2.0f + 0.5f);
+ v += d;
+ }
+ sm.Synthesizer().WaveTables().push_back(std::move(sintbl));
+ }
+
+
+
+
+ // ::OutputDebugStringW((boost::wformat(L"waveTable size: %d") % osc_[0].WaveData().size()).str().c_str());
+
+ // timberのセットアップ
+ for(int i = 0; i < 4;++i){
+
+ sf::Synthesizer::Timber timber;
+ timber.oscillator.reset(new sf::Synthesizer::WaveTableOscillator(&sm.Synthesizer().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 = &(sm.Synthesizer().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 = &(sm.Synthesizer().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 = &(sm.Synthesizer().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 = 5.0f;
+ timber.filter.lfo.gain = 1.0f;
+ timber.filter.lfo.waveForm = &(sm.Synthesizer().WaveTables()[3]);
+ timber.filter.lfo.startNoteOn = true;
+ timber.filter.cutoff = 10000.0f;
+ timber.filter.resonance = 0.0f;
+ timber.filter.envelope.attackTime = 0.01f;
+ timber.filter.envelope.decayTime = 0.03f;
+ timber.filter.envelope.sustainLevel = 0.05f;
+ timber.filter.envelope.releaseTime = 0.2f;
+ timber.filter.envelope.gain = 10000.0f;
+
+ sm.Synthesizer().AddProgram(sf::Synthesizer::Program(std::move((boost::wformat(L"Program No.%d") % i).str()),std::move(timber)));
+ // timbers_.push_back(std::move(timber));
+ }
+
+ for(int i = 0,end = sm.Synthesizer().Voices();i < end;++i)
+ {
+ sm.Synthesizer().AssignProgramToVoice(0,i);
+ }
+
+ sm.Synthesizer().isEnable(true);
+}
+
+void App::StartSound()
+{
+ if(isDestroy_) {
+ isDestroy_ = false;
+ // サウンド再生スレッドの開始
+ soundTask_ = task<void>(create_async([this]()
+ {
+ ExecuteSoundThread();
+ })
+ );
+ }
+}
+
+void App::StopSound()
+{
+ // サウンド再生スレッドの停止
+ if(!isDestroy_){
+ isDestroy_ = true;
+ WaitForSingleObjectEx(soundStopped_.get(),INFINITE,FALSE);
+ }
+}
+// サウンド再生スレッド
+void App::ExecuteSoundThread()
+{
+ //sf::com_init comInit;
+ // InitSound();
+ soundManager_->Sequencer().Play();
+ while(!isDestroy_)
+ {
+ soundDriver_->Render();
+ // Concurrency::wait(800);
+ // soundDriver_->Update();
+ // soundDriver_->Render();
+ }
+ ::SetEvent(soundStopped_.get());
+ //isDestroy_ = false;
+}
\ No newline at end of file
--- /dev/null
+//
+// App.xaml.h
+// App クラスの宣言。
+//
+
+#pragma once
+
+#include "App.g.h"
+#include "SoundDriver.h"
+#include "SoundManager.h"
+
+namespace SynthApp
+{
+ /// <summary>
+ /// 既定の Application クラスを補完するアプリケーション固有の動作を提供します。
+ /// </summary>
+ ref class App sealed
+ {
+ public:
+ App();
+ ~App();
+ virtual void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ pArgs) override;
+
+ private:
+ void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ e);
+ void InitSound();
+ void StartSound();
+ void StopSound();
+ void ExecuteSoundThread();
+
+ bool isDestroy_;
+ std::unique_ptr<sf::SoundManager> soundManager_;
+ std::unique_ptr<sf::SoundDriver> soundDriver_;
+ concurrency::task<void> soundTask_;
+ sf::handle_holder soundStopped_;
+
+ };
+}
--- /dev/null
+//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+//// PARTICULAR PURPOSE.
+////
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+#pragma once
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+// Common Constants
+
+#define PI_F 3.1415927f
+
+// Template Vector & Matrix Classes
+
+template <class T> struct Vector2
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ };
+ struct
+ {
+ T r;
+ T g;
+ };
+ struct
+ {
+ T u;
+ T v;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { }
+};
+
+template <class T> struct Vector3
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ T z;
+ };
+ struct
+ {
+ T r;
+ T g;
+ T b;
+ };
+ struct
+ {
+ T u;
+ T v;
+ T w;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { }
+};
+
+template <class T> struct Vector4
+{
+ union
+ {
+ struct
+ {
+ T x;
+ T y;
+ T z;
+ T w;
+ };
+ struct
+ {
+ T r;
+ T g;
+ T b;
+ T a;
+ };
+ };
+
+ T& operator[](unsigned int index)
+ {
+ return static_cast<T*>(this)[index];
+ }
+
+ Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { }
+};
+
+template <class T> struct Matrix4x4
+{
+ union
+ {
+ struct
+ {
+ T _11; T _12; T _13; T _14;
+ T _21; T _22; T _23; T _24;
+ T _31; T _32; T _33; T _34;
+ T _41; T _42; T _43; T _44;
+ };
+ struct
+ {
+ T _m00; T _m01; T _m02; T _m03;
+ T _m10; T _m11; T _m12; T _m13;
+ T _m20; T _m21; T _m22; T _m23;
+ T _m30; T _m31; T _m32; T _m33;
+ };
+ };
+
+ Matrix4x4(T value = 0)
+ {
+ _11 = _12 = _13 = _14 = value;
+ _21 = _22 = _23 = _24 = value;
+ _31 = _32 = _33 = _34 = value;
+ _41 = _42 = _43 = _44 = value;
+ }
+
+ Matrix4x4(
+ T i11, T i12, T i13, T i14,
+ T i21, T i22, T i23, T i24,
+ T i31, T i32, T i33, T i34,
+ T i41, T i42, T i43, T i44
+ )
+ {
+ _11 = i11; _12 = i12; _13 = i13; _14 = i14;
+ _21 = i21; _22 = i22; _23 = i23; _24 = i24;
+ _31 = i31; _32 = i32; _33 = i33; _34 = i34;
+ _41 = i41; _42 = i42; _43 = i43; _44 = i44;
+ }
+
+ T* operator[](unsigned int index)
+ {
+ return &(reinterpret_cast<T*>(this)[index*4]);
+ }
+};
+
+// Template Vector Operations
+
+template <class T>
+T dot(Vector2<T> a, Vector2<T> b)
+{
+ return a.x * b.x + a.y * b.y;
+}
+
+template <class T>
+T dot(Vector3<T> a, Vector3<T> b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+template <class T>
+T dot(Vector4<T> a, Vector4<T> b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z + a.w + b.w;
+}
+
+template <class T>
+T length(Vector2<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y);
+}
+
+template <class T>
+T length(Vector3<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
+}
+
+template <class T>
+T length(Vector4<T> a)
+{
+ return sqrt(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w);
+}
+
+template <class T>
+Vector3<T> cross(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x));
+}
+
+template <class T>
+Vector2<T> normalize(Vector2<T> a)
+{
+ T len = length(a);
+ return Vector2<T>(a.x / len, a.y / len);
+}
+
+template <class T>
+Vector3<T> normalize(Vector3<T> a)
+{
+ T len = length(a);
+ return Vector3<T>(a.x / len, a.y / len, a.z / len);
+}
+
+template <class T>
+Vector4<T> normalize(Vector4<T> a)
+{
+ T len = length(a);
+ return Vector4<T>(a.x / len, a.y / len, a.z / len, a.w / len);
+}
+
+// Template Vector Operators
+
+template <class T>
+Vector2<T> operator-(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x - b.x, a.y - b.y);
+}
+
+template <class T>
+Vector2<T> operator-(Vector2<T> a)
+{
+ return Vector2<T>( -a.x, -a.y);
+}
+
+template <class T>
+Vector3<T> operator-(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+template <class T>
+Vector3<T> operator-(Vector3<T> a)
+{
+ return Vector3<T>( -a.x, -a.y, -a.z);
+}
+
+template <class T>
+Vector4<T> operator-(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
+
+template <class T>
+Vector4<T> operator-(Vector4<T> a)
+{
+ return Vector4<T>( -a.x, -a.y, -a.z, -a.w);
+}
+
+template <class T>
+Vector2<T> operator+(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x + b.x, a.y + b.y);
+}
+
+template <class T>
+Vector3<T> operator+(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+template <class T>
+Vector4<T> operator+(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
+
+template <class T>
+Vector2<T> operator*(Vector2<T> a, T s)
+{
+ return Vector2<T>(a.x * s, a.y * s);
+}
+
+template <class T>
+Vector2<T> operator*(T s, Vector2<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector2<T> operator*(Vector2<T> a, Vector2<T> b)
+{
+ return Vector2<T>(a.x * b.x, a.y * b.y);
+}
+
+template <class T>
+Vector2<T> operator/(Vector2<T> a, T s)
+{
+ return Vector2<T>(a.x / s, a.y / s);
+}
+
+template <class T>
+Vector3<T> operator*(Vector3<T> a, T s)
+{
+ return Vector3<T>(a.x * s, a.y * s, a.z * s);
+}
+
+template <class T>
+Vector3<T> operator*(T s, Vector3<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector3<T> operator*(Vector3<T> a, Vector3<T> b)
+{
+ return Vector3<T>(a.x * b.x, a.y * b.y, a.z * b.z);
+}
+
+template <class T>
+Vector3<T> operator/(Vector3<T> a, T s)
+{
+ return Vector3<T>(a.x / s, a.y / s, a.z / s);
+}
+
+template <class T>
+Vector4<T> operator*(Vector4<T> a, T s)
+{
+ return Vector4<T>(a.x * s, a.y * s, a.z * s, a.w * s);
+}
+
+template <class T>
+Vector4<T> operator*(T s, Vector4<T> a)
+{
+ return a * s;
+}
+
+template <class T>
+Vector4<T> operator*(Vector4<T> a, Vector4<T> b)
+{
+ return Vector4<T>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+}
+
+template <class T>
+Vector4<T> operator/(Vector4<T> a, T s)
+{
+ return Vector4<T>(a.x / s, a.y / s, a.z / s, a.w / s);
+}
+
+
+
+// Template Matrix Operations
+
+template <class T>
+Matrix4x4<T> transpose(Matrix4x4<T> m)
+{
+ return Matrix4x4<T>(
+ m._11, m._21, m._31, m._41,
+ m_.12, m._22, m._32, m._42,
+ m._13, m._23, m._33, m._43,
+ m._14, m._24, m._34, m._44
+ );
+}
+
+template <class T>
+Matrix4x4<T> mul(Matrix4x4<T> m1, Matrix4x4<T> m2)
+{
+ Matrix4x4<T> mOut;
+
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ for (int k = 0; k < 4; k++)
+ {
+ mOut[i][j] += m1[i][k] * m2[k][j];
+ }
+ }
+ }
+
+ return mOut;
+}
+
+// Common HLSL-compatible vector typedefs
+
+typedef unsigned int uint;
+
+typedef Vector2<float> float2;
+typedef Vector3<float> float3;
+typedef Vector4<float> float4;
+
+typedef Matrix4x4<float> float4x4;
+
+// Standard Matrix Intializers
+
+inline float4x4 identity()
+{
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 translation(float x, float y, float z)
+{
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = x;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = y;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = z;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 scale(float x, float y, float z)
+{
+ float4x4 mOut;
+
+ mOut._11 = x; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = y; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = z; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationX(float degreeX)
+{
+ float angleInRadians = degreeX * (PI_F / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationY(float degreeY)
+{
+ float angleInRadians = degreeY * (PI_F / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f;
+ mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+inline float4x4 rotationZ(float degreeZ)
+{
+ float angleInRadians = degreeZ * (PI_F / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+
+ float4x4 mOut;
+
+ mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f;
+ mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f;
+ mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
+ mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
+
+ return mOut;
+}
+
+// 3D Rotation matrix for an arbitrary axis specified by x, y and z
+inline float4x4 rotationArbitrary(float3 axis, float degree)
+{
+ axis = normalize(axis);
+
+ float angleInRadians = degree * (PI_F / 180.0f);
+
+ float sinAngle = sinf(angleInRadians);
+ float cosAngle = cosf(angleInRadians);
+ float oneMinusCosAngle = 1 - cosAngle;
+
+ float4x4 mOut;
+
+ mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f);
+ mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y;
+ mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z;
+ mOut._41 = 0.0f;
+
+ mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x;
+ mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f);
+ mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z;
+ mOut._24 = 0.0f;
+
+ mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x;
+ mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y;
+ mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f);
+ mOut._34 = 0.0f;
+
+ mOut._41 = 0.0f;
+ mOut._42 = 0.0f;
+ mOut._43 = 0.0f;
+ mOut._44 = 1.0f;
+
+ return mOut;
+}
--- /dev/null
+<!--
+ This file contains XAML styles that simplify application development.
+
+ These are not merely convenient, but are required by most Visual Studio project and item templates.
+ Removing, renaming, or otherwise modifying the content of these files may result in a project that
+ does not build, or that will not build once additional pages are added. If variations on these
+ styles are desired it is recommended that you copy the content under a new name and modify your
+ private copy.
+-->
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <!-- Non-brush values that vary across themes -->
+
+ <ResourceDictionary.ThemeDictionaries>
+ <ResourceDictionary x:Key="Default">
+ <x:String x:Key="BackButtonGlyph"></x:String>
+ <x:String x:Key="BackButtonSnappedGlyph"></x:String>
+ </ResourceDictionary>
+
+ <ResourceDictionary x:Key="HighContrast">
+ <x:String x:Key="BackButtonGlyph"></x:String>
+ <x:String x:Key="BackButtonSnappedGlyph"></x:String>
+ </ResourceDictionary>
+ </ResourceDictionary.ThemeDictionaries>
+
+ <!-- RichTextBlock styles -->
+
+ <Style x:Key="BasicRichTextStyle" TargetType="RichTextBlock">
+ <Setter Property="Foreground" Value="{StaticResource ApplicationForegroundThemeBrush}"/>
+ <Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
+ <Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
+ <Setter Property="TextTrimming" Value="WordEllipsis"/>
+ <Setter Property="TextWrapping" Value="Wrap"/>
+ <Setter Property="Typography.StylisticSet20" Value="True"/>
+ <Setter Property="Typography.DiscretionaryLigatures" Value="True"/>
+ <Setter Property="Typography.CaseSensitiveForms" Value="True"/>
+ </Style>
+
+ <Style x:Key="BaselineRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BasicRichTextStyle}">
+ <Setter Property="LineHeight" Value="20"/>
+ <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
+ <!-- Properly align text along its baseline -->
+ <Setter Property="RenderTransform">
+ <Setter.Value>
+ <TranslateTransform X="-1" Y="4"/>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="ItemRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaselineRichTextStyle}"/>
+
+ <Style x:Key="BodyRichTextStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaselineRichTextStyle}">
+ <Setter Property="FontWeight" Value="SemiLight"/>
+ </Style>
+
+ <!-- TextBlock styles -->
+
+ <Style x:Key="BasicTextStyle" TargetType="TextBlock">
+ <Setter Property="Foreground" Value="{StaticResource ApplicationForegroundThemeBrush}"/>
+ <Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
+ <Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
+ <Setter Property="TextTrimming" Value="WordEllipsis"/>
+ <Setter Property="TextWrapping" Value="Wrap"/>
+ <Setter Property="Typography.StylisticSet20" Value="True"/>
+ <Setter Property="Typography.DiscretionaryLigatures" Value="True"/>
+ <Setter Property="Typography.CaseSensitiveForms" Value="True"/>
+ </Style>
+
+ <Style x:Key="BaselineTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
+ <Setter Property="LineHeight" Value="20"/>
+ <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
+ <!-- Properly align text along its baseline -->
+ <Setter Property="RenderTransform">
+ <Setter.Value>
+ <TranslateTransform X="-1" Y="4"/>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="HeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
+ <Setter Property="FontSize" Value="56"/>
+ <Setter Property="FontWeight" Value="Light"/>
+ <Setter Property="LineHeight" Value="40"/>
+ <Setter Property="RenderTransform">
+ <Setter.Value>
+ <TranslateTransform X="-2" Y="8"/>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="SubheaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
+ <Setter Property="FontSize" Value="26.667"/>
+ <Setter Property="FontWeight" Value="Light"/>
+ <Setter Property="LineHeight" Value="30"/>
+ <Setter Property="RenderTransform">
+ <Setter.Value>
+ <TranslateTransform X="-1" Y="6"/>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="TitleTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
+ <Setter Property="FontWeight" Value="SemiBold"/>
+ </Style>
+
+ <Style x:Key="ItemTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}"/>
+
+ <Style x:Key="BodyTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
+ <Setter Property="FontWeight" Value="SemiLight"/>
+ </Style>
+
+ <Style x:Key="CaptionTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaselineTextStyle}">
+ <Setter Property="FontSize" Value="12"/>
+ <Setter Property="Foreground" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}"/>
+ </Style>
+
+ <!-- Button styles -->
+
+ <!--
+ TextButtonStyle is used to style a Button using subheader-styled text with no other adornment. This
+ style is used in the GroupedItemsPage as a group header and in the FileOpenPickerPage for triggering
+ commands.
+ -->
+ <Style x:Key="TextButtonStyle" TargetType="Button">
+ <Setter Property="MinWidth" Value="0"/>
+ <Setter Property="MinHeight" Value="0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid Background="Transparent">
+ <TextBlock x:Name="Text" Text="{TemplateBinding Content}" Margin="3,-7,3,10" TextWrapping="NoWrap" Style="{StaticResource SubheaderTextStyle}"/>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5"/>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity"/>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!--
+ TextRadioButtonStyle is used to style a RadioButton using subheader-styled text with no other adornment.
+ This style is used in the SearchResultsPage to allow selection among filters.
+ -->
+ <Style x:Key="TextRadioButtonStyle" TargetType="RadioButton">
+ <Setter Property="MinWidth" Value="0"/>
+ <Setter Property="MinHeight" Value="0"/>
+ <Setter Property="Margin" Value="0,0,30,0"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="RadioButton">
+ <Grid Background="Transparent">
+ <TextBlock x:Name="Text" Text="{TemplateBinding Content}" Margin="3,-7,3,10" TextWrapping="NoWrap" Style="{StaticResource SubheaderTextStyle}"/>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5"/>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ButtonDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity"/>
+ <DoubleAnimation Duration="0" To="1" Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="CheckStates">
+ <VisualState x:Name="Checked"/>
+ <VisualState x:Name="Unchecked">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Indeterminate"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!--
+ AppBarButtonStyle is used to style a Button for use in an App Bar. Content will be centered and should fit within
+ the 40-pixel radius glyph provided. 16-point Segoe UI Symbol is used for content text to simplify the use of glyphs
+ from that font. AutomationProperties.Name is used for the text below the glyph.
+ -->
+ <Style x:Key="AppBarButtonStyle" TargetType="Button">
+ <Setter Property="Foreground" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
+ <Setter Property="VerticalAlignment" Value="Stretch"/>
+ <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
+ <Setter Property="FontWeight" Value="Normal"/>
+ <Setter Property="FontSize" Value="20"/>
+ <Setter Property="AutomationProperties.ItemType" Value="App Bar Button"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid x:Name="RootGrid" Width="100" Background="Transparent">
+ <StackPanel VerticalAlignment="Top" Margin="0,12,0,11">
+ <Grid Width="40" Height="40" Margin="0,0,0,5" HorizontalAlignment="Center">
+ <TextBlock x:Name="BackgroundGlyph" Text="" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemBackgroundThemeBrush}"/>
+ <TextBlock x:Name="OutlineGlyph" Text="" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0"/>
+ <ContentPresenter x:Name="Content" HorizontalAlignment="Center" Margin="-1,-1,0,0" VerticalAlignment="Center"/>
+ </Grid>
+ <TextBlock x:Name="TextLabel" Text="{TemplateBinding AutomationProperties.Name}" Foreground="{StaticResource AppBarItemForegroundThemeBrush}" Margin="0,0,2,0" FontSize="12" TextAlignment="Center" Width="88" MaxHeight="32" TextTrimming="WordEllipsis" Style="{StaticResource BasicTextStyle}"/>
+ </StackPanel>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5"/>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="ApplicationViewStates">
+ <VisualState x:Name="FullScreenLandscape"/>
+ <VisualState x:Name="Filled"/>
+ <VisualState x:Name="FullScreenPortrait">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Width">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="60"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Snapped">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Width">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="60"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemPressedForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="OutlineGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextLabel" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource AppBarItemDisabledForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!-- Standard App Bar buttons -->
+
+ <Style x:Key="SkipBackAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="SkipBackAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Skip Back"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="SkipAheadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="SkipAheadAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Skip Ahead"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="PlayAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="PlayAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Play"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="PauseAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="PauseAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Pause"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="EditAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="EditAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Edit"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="SaveAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="SaveAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Save"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="DeleteAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="DeleteAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Delete"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="DiscardAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="DiscardAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Discard"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="RemoveAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="RemoveAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Remove"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="AddAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="AddAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Add"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="NoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="NoAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="No"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="YesAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="YesAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Yes"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="MoreAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="MoreAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="More"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="RedoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="RedoAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Redo"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="UndoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="UndoAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Undo"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="HomeAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="HomeAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Home"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="OutAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="OutAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Out"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="NextAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="NextAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Next"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="PreviousAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="PreviousAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Previous"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="FavoriteAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="FavoriteAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Favorite"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="PhotoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="PhotoAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Photo"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="SettingsAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="SettingsAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Settings"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="VideoAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="VideoAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Video"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="RefreshAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="RefreshAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Refresh"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="DownloadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="DownloadAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Download"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="MailAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="MailAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Mail"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="SearchAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="SearchAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Search"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="HelpAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="HelpAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Help"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="UploadAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="UploadAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Upload"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="PinAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="PinAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Pin"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+ <Style x:Key="UnpinAppBarButtonStyle" TargetType="Button" BasedOn="{StaticResource AppBarButtonStyle}">
+ <Setter Property="AutomationProperties.AutomationId" Value="UnpinAppBarButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Unpin"/>
+ <Setter Property="Content" Value=""/>
+ </Style>
+
+ <!-- Title area styles -->
+
+ <Style x:Key="PageHeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource HeaderTextStyle}">
+ <Setter Property="TextWrapping" Value="NoWrap"/>
+ <Setter Property="VerticalAlignment" Value="Bottom"/>
+ <Setter Property="Margin" Value="0,0,30,40"/>
+ </Style>
+
+ <Style x:Key="PageSubheaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource SubheaderTextStyle}">
+ <Setter Property="TextWrapping" Value="NoWrap"/>
+ <Setter Property="VerticalAlignment" Value="Bottom"/>
+ <Setter Property="Margin" Value="0,0,0,40"/>
+ </Style>
+
+ <Style x:Key="SnappedPageHeaderTextStyle" TargetType="TextBlock" BasedOn="{StaticResource PageSubheaderTextStyle}">
+ <Setter Property="Margin" Value="0,0,18,40"/>
+ </Style>
+
+ <!--
+ BackButtonStyle is used to style a Button for use in the title area of a page. Margins appropriate for
+ the conventional page layout are included as part of the style.
+ -->
+ <Style x:Key="BackButtonStyle" TargetType="Button">
+ <Setter Property="MinWidth" Value="0"/>
+ <Setter Property="Width" Value="48"/>
+ <Setter Property="Height" Value="48"/>
+ <Setter Property="Margin" Value="36,0,36,36"/>
+ <Setter Property="VerticalAlignment" Value="Bottom"/>
+ <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
+ <Setter Property="FontWeight" Value="Normal"/>
+ <Setter Property="FontSize" Value="56"/>
+ <Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Back"/>
+ <Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid x:Name="RootGrid">
+ <Grid Margin="-1,-16,0,0">
+ <TextBlock x:Name="BackgroundGlyph" Text="" Foreground="{StaticResource BackButtonBackgroundThemeBrush}"/>
+ <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonGlyph}" Foreground="{StaticResource BackButtonForegroundThemeBrush}"/>
+ <TextBlock x:Name="ArrowGlyph" Text="" Foreground="{StaticResource BackButtonPressedForegroundThemeBrush}" Opacity="0"/>
+ </Grid>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5"/>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <DoubleAnimation Storyboard.TargetName="ArrowGlyph" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ <DoubleAnimation Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!--
+ PortraitBackButtonStyle is used to style a Button for use in the title area of a portrait page. Margins appropriate
+ for the conventional page layout are included as part of the style.
+ -->
+ <Style x:Key="PortraitBackButtonStyle" TargetType="Button" BasedOn="{StaticResource BackButtonStyle}">
+ <Setter Property="Margin" Value="26,0,26,36"/>
+ </Style>
+
+ <!--
+ SnappedBackButtonStyle is used to style a Button for use in the title area of a snapped page. Margins appropriate
+ for the conventional page layout are included as part of the style.
+
+ The obvious duplication here is necessary as the glyphs used in snapped are not merely smaller versions of the same
+ glyph but are actually distinct.
+ -->
+ <Style x:Key="SnappedBackButtonStyle" TargetType="Button">
+ <Setter Property="MinWidth" Value="0"/>
+ <Setter Property="Margin" Value="20,0,0,0"/>
+ <Setter Property="VerticalAlignment" Value="Bottom"/>
+ <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
+ <Setter Property="FontWeight" Value="Normal"/>
+ <Setter Property="FontSize" Value="26.66667"/>
+ <Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
+ <Setter Property="AutomationProperties.Name" Value="Back"/>
+ <Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="Button">
+ <Grid x:Name="RootGrid" Width="36" Height="36" Margin="-3,0,7,33">
+ <Grid Margin="-1,-1,0,0">
+ <TextBlock x:Name="BackgroundGlyph" Text="" Foreground="{StaticResource BackButtonBackgroundThemeBrush}"/>
+ <TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="{StaticResource BackButtonForegroundThemeBrush}"/>
+ <TextBlock x:Name="ArrowGlyph" Text="" Foreground="{StaticResource BackButtonPressedForegroundThemeBrush}" Opacity="0"/>
+ </Grid>
+ <Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5"/>
+ <Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5"/>
+
+ <VisualStateManager.VisualStateGroups>
+ <VisualStateGroup x:Name="CommonStates">
+ <VisualState x:Name="Normal"/>
+ <VisualState x:Name="PointerOver">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Pressed">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonForegroundThemeBrush}"/>
+ </ObjectAnimationUsingKeyFrames>
+ <DoubleAnimation Storyboard.TargetName="ArrowGlyph" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ <DoubleAnimation Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Disabled">
+ <Storyboard>
+ <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
+ <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
+ </ObjectAnimationUsingKeyFrames>
+ </Storyboard>
+ </VisualState>
+ </VisualStateGroup>
+ <VisualStateGroup x:Name="FocusStates">
+ <VisualState x:Name="Focused">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ <DoubleAnimation Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
+ </Storyboard>
+ </VisualState>
+ <VisualState x:Name="Unfocused"/>
+ <VisualState x:Name="PointerFocused"/>
+ </VisualStateGroup>
+ </VisualStateManager.VisualStateGroups>
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <!-- Item templates -->
+
+ <!-- Grid-appropriate 250 pixel square item template as seen in the GroupedItemsPage and ItemsPage -->
+ <DataTemplate x:Key="Standard250x250ItemTemplate">
+ <Grid HorizontalAlignment="Left" Width="250" Height="250">
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel VerticalAlignment="Bottom" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
+ <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Height="60" Margin="15,0,15,0"/>
+ <TextBlock Text="{Binding Subtitle}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!-- Grid-appropriate 500 by 130 pixel item template as seen in the GroupDetailPage -->
+ <DataTemplate x:Key="Standard500x130ItemTemplate">
+ <Grid Height="110" Width="480" Margin="10">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
+ <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!-- List-appropriate 130 pixel high item template as seen in the SplitPage -->
+ <DataTemplate x:Key="Standard130ItemTemplate">
+ <Grid Height="110" Margin="6">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
+ <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!--
+ List-appropriate 80 pixel high item template as seen in the SplitPage when Filled, and
+ the following pages when snapped: GroupedItemsPage, GroupDetailPage, and ItemsPage
+ -->
+ <DataTemplate x:Key="Standard80ItemTemplate">
+ <Grid Margin="6">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel Grid.Column="1" Margin="10,0,0,0">
+ <TextBlock Text="{Binding Title}" Style="{StaticResource ItemTextStyle}" MaxHeight="40"/>
+ <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!-- Grid-appropriate 300 by 70 pixel item template as seen in the SearchResultsPage -->
+ <DataTemplate x:Key="StandardSmallIcon300x70ItemTemplate">
+ <Grid Width="294" Margin="6">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,0,0,10" Width="40" Height="40">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel Grid.Column="1" Margin="10,-10,0,0">
+ <TextBlock Text="{Binding Title}" Style="{StaticResource BodyTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" TextWrapping="NoWrap"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!-- List-appropriate 70 pixel high item template as seen in the SearchResultsPage when Snapped -->
+ <DataTemplate x:Key="StandardSmallIcon70ItemTemplate">
+ <Grid Margin="6">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,0,0,10" Width="40" Height="40">
+ <Image Source="{Binding Image}" Stretch="UniformToFill"/>
+ </Border>
+ <StackPanel Grid.Column="1" Margin="10,-10,0,0">
+ <TextBlock Text="{Binding Title}" Style="{StaticResource BodyTextStyle}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" TextWrapping="NoWrap"/>
+ <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" TextWrapping="NoWrap"/>
+ </StackPanel>
+ </Grid>
+ </DataTemplate>
+
+ <!--
+ 190x130 pixel item template for displaying file previews as seen in the FileOpenPickerPage
+ Includes an elaborate tooltip to display title and description text
+ -->
+ <DataTemplate x:Key="StandardFileWithTooltip190x130ItemTemplate">
+ <Grid>
+ <Grid Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
+ <Image Source="{Binding Image}" Width="190" Height="130" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform"/>
+ </Grid>
+ <ToolTipService.Placement>Mouse</ToolTipService.Placement>
+ <ToolTipService.ToolTip>
+ <ToolTip>
+ <ToolTip.Style>
+ <Style TargetType="ToolTip">
+ <Setter Property="BorderBrush" Value="{StaticResource ToolTipBackgroundThemeBrush}"/>
+ <Setter Property="Padding" Value="0"/>
+ </Style>
+ </ToolTip.Style>
+
+ <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="20">
+ <Image Source="{Binding Image}" Width="160" Height="160" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform"/>
+ </Grid>
+ <StackPanel Width="200" Grid.Column="1" Margin="0,20,20,20">
+ <TextBlock Text="{Binding Title}" TextWrapping="NoWrap" Style="{StaticResource BodyTextStyle}"/>
+ <TextBlock Text="{Binding Description}" MaxHeight="140" Foreground="{StaticResource ApplicationSecondaryForegroundThemeBrush}" Style="{StaticResource BodyTextStyle}"/>
+ </StackPanel>
+ </Grid>
+ </ToolTip>
+ </ToolTipService.ToolTip>
+ </Grid>
+ </DataTemplate>
+
+ <!-- ScrollViewer styles -->
+
+ <Style x:Key="HorizontalScrollViewerStyle" TargetType="ScrollViewer">
+ <Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="VerticalScrollBarVisibility" Value="Disabled"/>
+ <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled"/>
+ <Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
+ <Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
+ </Style>
+
+ <Style x:Key="VerticalScrollViewerStyle" TargetType="ScrollViewer">
+ <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
+ <Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
+ <Setter Property="ScrollViewer.VerticalScrollMode" Value="Enabled"/>
+ <Setter Property="ScrollViewer.ZoomMode" Value="Disabled"/>
+ </Style>
+
+ <!-- Page layout roots typically use entrance animations and a theme-appropriate background color -->
+
+ <Style x:Key="LayoutRootStyle" TargetType="Panel">
+ <Setter Property="Background" Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
+ <Setter Property="ChildrenTransitions">
+ <Setter.Value>
+ <TransitionCollection>
+ <EntranceThemeTransition/>
+ </TransitionCollection>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
--- /dev/null
+<Page
+ x:Class="SynthApp.MainPage"
+ IsTabStop="false"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="using:SynthApp"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d">
+
+ <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
+
+ </Grid>
+</Page>
--- /dev/null
+//
+// MainPage.xaml.cpp
+// Implementation of the MainPage class.
+//
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+
+using namespace SynthApp;
+
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+MainPage::MainPage()
+{
+ InitializeComponent();
+}
+
+/// <summary>
+/// Invoked when this page is about to be displayed in a Frame.
+/// </summary>
+/// <param name="e">Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.</param>
+void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ (void) e; // Unused parameter
+}
--- /dev/null
+//
+// MainPage.xaml.h
+// Declaration of the MainPage class.
+//
+
+#pragma once
+
+#include "MainPage.g.h"
+
+namespace SynthApp
+{
+ /// <summary>
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ /// </summary>
+ public ref class MainPage sealed
+ {
+ public:
+ MainPage();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ };
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
+
+ <Identity Name="5aabb38f-3132-4a61-ba6f-f65267da5ff1"
+ Publisher="CN=sfpgm_000"
+ Version="1.0.0.0" />
+
+ <Properties>
+ <DisplayName>SynthApp</DisplayName>
+ <PublisherDisplayName>sfpgm_000</PublisherDisplayName>
+ <Logo>Assets\StoreLogo.png</Logo>
+ </Properties>
+
+ <Prerequisites>
+ <OSMinVersion>6.2.0</OSMinVersion>
+ <OSMaxVersionTested>6.2.0</OSMaxVersionTested>
+ </Prerequisites>
+
+ <Resources>
+ <Resource Language="x-generate"/>
+ </Resources>
+
+ <Applications>
+ <Application Id="App"
+ Executable="$targetnametoken$.exe"
+ EntryPoint="SynthApp.App">
+ <VisualElements
+ DisplayName="SynthApp"
+ Logo="Assets\Logo.png"
+ SmallLogo="Assets\SmallLogo.png"
+ Description="SynthApp"
+ ForegroundText="light"
+ BackgroundColor="#464646">
+ <DefaultTile ShowName="allLogos" />
+ <SplashScreen Image="Assets\SplashScreen.png" />
+ </VisualElements>
+ </Application>
+ </Applications>
+ <Capabilities>
+ <Capability Name="internetClient" />
+ </Capabilities>
+</Package>
\ No newline at end of file
--- /dev/null
+#include "pch.h"
+#include "Sequencer.h"
+
+namespace sf {
+
+ 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),status_(Status::Stop)
+ {
+ Update();
+ for(int i = 0,end = synth_.Voices();i < end;++i)
+ {
+ gateBuffer_.push_back(0);
+ currentIndexs_.push_back(0);
+ SequenceTracks_.push_back(SequenceDatasType());
+ }
+ }
+
+ void Reset()
+ {
+ for(int i = 0,end = synth_.Voices();i < end;++i)
+ {
+ gateBuffer_.at(i) = 0;
+ currentIndexs_.at(i) = 0;
+ }
+ }
+ 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()
+ {
+ if(status_ == Status::Play){
+ 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_;}
+
+ void Play()
+ {
+ status_ = Status::Play;
+ }
+
+ void Pause()
+ {
+ status_ = Status::Pause;
+ }
+
+ void Stop()
+ {
+ status_ = Status::Stop;
+ Reset();
+ }
+
+ 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_;
+ Status status_;
+ };
+
+ Sequencer::Sequencer(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format) : impl_(new impl(synth,format))
+ {
+
+ }
+
+ 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();}
+ void Sequencer::Play()
+ {
+ impl_->Play();
+ }
+
+ void Sequencer::Pause()
+ {
+ impl_->Pause();
+ }
+
+ void Sequencer::Stop()
+ {
+ impl_->Stop();
+ }
+
+ SequenceTracksType& Sequencer::SequenceTracks() {return impl_->SequenceTracks();}
+
+
+
+}
--- /dev/null
+#pragma once
+#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
+ {
+ enum struct Status
+ {
+ Play,Stop,Pause
+ };
+
+ Sequencer(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format);
+ void Process();
+ ~Sequencer();
+
+ float TimeBase() const;
+ void TimeBase(float v);
+
+ float Tempo() const;
+ void Tempo(float v);
+
+ void Play();
+ void Pause();
+ void Stop();
+ SequenceTracksType& SequenceTracks();
+ private:
+ struct impl;
+ std::unique_ptr<impl> impl_;
+ };
+}
--- /dev/null
+#include "pch.h"
+#include "sf_memory.h"
+#include "SoundDriver.h"
+using namespace std;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Devices::Enumeration;
+using namespace Windows::Media::Devices;
+using namespace Concurrency;
+using namespace Platform;
+#pragma comment(lib, "mmdevapi.lib")
+
+namespace stps = std::placeholders;
+using namespace Microsoft::WRL;
+
+namespace {
+ 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,
+ const GUID& sub_type = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
+ {
+ ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));
+ format.Format.wFormatTag = type;
+ format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+ format.SubFormat = sub_type;
+ format.Format.nSamplesPerSec = sample_rate;
+ format.Format.nChannels = channels;
+ format.Format.wBitsPerSample = bits_per_sample;
+ format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;
+ format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
+ format.Samples.wValidBitsPerSample = valid_bits_per_sample;
+ format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+ }
+
+ void makeWaveFormat(WAVEFORMATEX& format,int sample_rate = 44100,int channels = 2,int bits = 16,uint32_t type = WAVE_FORMAT_PCM)
+ {
+ ZeroMemory(&format,sizeof(WAVEFORMATEX));
+ format.wFormatTag = type;
+ format.nSamplesPerSec = sample_rate;
+ format.nChannels = channels;
+ format.wBitsPerSample = bits;
+ format.nBlockAlign = (format.wBitsPerSample / 8) * format.nChannels;
+ format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+ };
+}
+
+namespace sf {
+
+ struct ActivateAudioInterfaceCompletionHandler
+ : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
+ {
+ ActivateAudioInterfaceCompletionHandler() :
+ hr_(S_OK),
+ ptr_(nullptr),
+ eventHolder_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)) {};
+
+ ~ActivateAudioInterfaceCompletionHandler(){};
+
+ // IActivateAudioInterfaceCompletionHandler
+ STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
+ {
+ HRESULT hr = S_OK;
+ HRESULT hrActivateResult = S_OK;
+ IUnknown *punkAudioInterface = nullptr;
+ // Check for a successful activation result
+ hr = operation->GetActivateResult( &hrActivateResult, &punkAudioInterface );
+ if(SUCCEEDED(hr)){
+ if (SUCCEEDED( hrActivateResult ))
+ {
+ hr_ = S_OK;
+ // Get the pointer for the Audio Client
+ punkAudioInterface->QueryInterface( IID_PPV_ARGS(&ptr_) );
+ if( nullptr == ptr_ )
+ {
+ hr_ = E_FAIL;
+ ::SetEvent(eventHolder_.get());
+ return hr_;
+ }
+ ::SetEvent(eventHolder_.get());
+ } else {
+ hr_ = hr = hrActivateResult;
+ ::SetEvent(eventHolder_.get());
+ }
+ } else {
+ hr_ = hr;
+ ::SetEvent(eventHolder_.get());
+ }
+ return hr;
+ //operation
+ // concurrency::wait(0);
+ }
+
+ void wait()
+ {
+ ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
+ }
+
+ HRESULT ResultCode() {return hr_;}
+ IAudioClient2Ptr AudioClient(){return ptr_;}
+ private:
+ HRESULT hr_;
+ sf::handle_holder eventHolder_;
+ IAudioClient2Ptr ptr_;
+ };
+
+ struct SoundDriver::impl
+ // : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
+ {
+
+ impl() : bufferIndex_(0),eventHolder_(nullptr),processBuffer_(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,stps::_1,stps::_2)),isStart_(false)
+ {
+ //::AvMMAvSetMmThreadCharacteristics
+ String^ deviceID = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
+
+ {
+ ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOpPtr;
+ IActivateAudioInterfaceAsyncOperation* asyncOp;
+ ComPtr<ActivateAudioInterfaceCompletionHandler> handler(Make<ActivateAudioInterfaceCompletionHandler>());
+ HRESULT hr = ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,handler.Get(),&asyncOp);
+ asyncOpPtr.Attach(asyncOp);
+ if(SUCCEEDED(hr)){
+ handler->wait();
+ if(handler->ResultCode() == S_OK)
+ {
+ audioClient_ = handler->AudioClient();
+ } else {
+ throw AudioClientNullException(L"\8aù\92è\82ÌAudioClient\82ð\83A\83N\83e\83B\83x\81[\83g\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
+ }
+ } else {
+ throw AudioClientNullException(L"\8aù\92è\82ÌAudioClient\82ð\83A\83N\83e\83B\83x\81[\83g\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
+ }
+ }
+ // \83I\81[\83f\83B\83I\83t\83H\81[\83}\83b\83g\82Ì\83`\83F\83b\83N
+ makeWaveFormat(format_);
+ //sf::co_task_memory<WAVEFORMATEXTENSIBLE> mix_format;
+ //audioClient_->GetMixFormat(reinterpret_cast<WAVEFORMATEX**>(&mix_format));
+ // format_ = *mix_format.get();
+
+ sf::co_task_memory<WAVEFORMATEXTENSIBLE> alt_format;
+ HRESULT hr = audioClient_->IsFormatSupported(
+ AUDCLNT_SHAREMODE_SHARED,
+ reinterpret_cast<WAVEFORMATEX*>(&format_),
+ reinterpret_cast<WAVEFORMATEX**>(&alt_format));
+ int sample_rate_backup = 0;
+ if(hr == S_FALSE) // FALSE\82Ì\8e\9e\82Í\82¨\82»\82ç\82\83T\83\93\83v\83\8a\83\93\83O\83\8c\81[\83g\82ª\88á\82¤
+ {
+ // \83T\83\93\83v\83\8a\83\93\83O\83\8c\81[\83g\82Ì\82Ý\82ª\88Ù\82È\82é\82©\83`\83F\83b\83N\82·\82é
+ if( alt_format->Format.wFormatTag == format_.Format.wFormatTag &&
+ alt_format->Format.nChannels == format_.Format.nChannels &&
+ alt_format->Format.wBitsPerSample == format_.Format.wBitsPerSample &&
+ alt_format->Samples.wValidBitsPerSample == format_.Samples.wValidBitsPerSample &&
+ alt_format->Format.nSamplesPerSec != format_.Format.nSamplesPerSec
+ )
+ {
+ sample_rate_backup = format_.Format.nSamplesPerSec;
+ // \91ã\91Ö\83t\83H\81[\83}\83b\83g\82Ì\83T\83\93\83v\83\8b\83\8c\81[\83g\82ð\83Z\83b\83g\82·\82é
+ format_.Format.nSamplesPerSec = alt_format->Format.nSamplesPerSec;
+ // \8dÄ\8cv\8eZ\82·\82é
+ format_.Format.nAvgBytesPerSec = alt_format->Format.nSamplesPerSec * format_.Format.nBlockAlign;
+ // \82à\82¤\88ê\89ñ\83`\83F\83b\83N\82·\82é\81B
+ // \83T\83\93\83v\83\8b\83\8c\81[\83g\88È\8aO\82Å\83T\83|\81[\83g\82µ\82Ä\82¢\82È\82¢\90Ý\92è\82ª\82 \82ê\82Î\97á\8aO\82ª\94\90¶\82·\82é\81B
+ alt_format.reset();
+ ThrowIfErr(audioClient_->IsFormatSupported(
+ AUDCLNT_SHAREMODE_SHARED,
+ reinterpret_cast<WAVEFORMATEX*>(&format_),
+ reinterpret_cast<WAVEFORMATEX**>(&alt_format)));
+ } else {
+ throw AudioFormatNotSupportedException(L"\82±\82Ì\83I\81[\83f\83B\83I\83f\83o\83C\83X\82Å\90Ý\92è\82µ\82Ä\82¢\82é\83t\83H\81[\83}\83b\83g\82Í\91Î\89\9e\82µ\82Ä\82¢\82Ü\82¹\82ñ\81B");
+ }
+ }
+
+ // Audio Client\82Ì\8f\89\8aú\89»
+
+ REFERENCE_TIME defaultDevicePeriod,minDevicePriod;
+ audioClient_->GetDevicePeriod(&defaultDevicePeriod,&minDevicePriod);
+ hr = audioClient_->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_NOPERSIST |
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK ,
+ minDevicePriod,0,
+ reinterpret_cast<WAVEFORMATEX*>(&format_),NULL);
+ if(hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
+ {
+ ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
+ latency_ = (double)10000000 * (bufferSize_) / format_.Format.nSamplesPerSec;
+ audioClient_.Reset();
+
+ ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOp;
+ ActivateAudioInterfaceCompletionHandler handler;
+ HRESULT hr = ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,&handler,&asyncOp);
+ if(SUCCEEDED(hr)){
+ handler.wait();
+ if(handler.ResultCode() == S_OK)
+ {
+ audioClient_ = handler.AudioClient();
+ } else {
+ throw AudioClientNullException(L"\8aù\92è\82ÌAudioClient\82ð\83A\83N\83e\83B\83x\81[\83g\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
+ }
+ } else {
+ throw AudioClientNullException(L"\8aù\92è\82ÌAudioClient\82ð\83A\83N\83e\83B\83x\81[\83g\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
+ }
+
+ ThrowIfErr(audioClient_->Initialize(
+ AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_NOPERSIST |
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK ,
+ latency_,0,
+ reinterpret_cast<WAVEFORMATEX*>(&format_),NULL));
+ } else {
+ ThrowIfErr(hr);
+ }
+
+ ThrowIfErr(audioClient_->GetBufferSize(&bufferSize_));
+
+ buffer_[0].reset((float*)_aligned_malloc( bufferSize_ * format_.Format.nBlockAlign,16));
+ buffer_[1].reset((float*)_aligned_malloc( bufferSize_ * format_.Format.nBlockAlign,16));
+ bufferByteCount_ = bufferSize_ * format_.Format.nBlockAlign;
+
+ audioClient_->GetStreamLatency(&latency_);
+ ThrowIfErr(audioClient_->GetService(__uuidof(IAudioRenderClient),&audioRenderClient_));
+ eventHolder_.reset(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE));
+ audioClient_->SetEventHandle(eventHolder_.get());
+
+ processBuffer_(buffer_[bufferIndex_],bufferSize_);
+ BYTE* rawBuffer;
+ ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
+ audioRenderClient_->ReleaseBuffer(bufferSize_,0);
+ bufferIndex_ = (bufferIndex_ + 1) & 0x1;
+ processBuffer_(buffer_[bufferIndex_],bufferSize_);
+
+ Start();
+
+ // ThrowIfErr(ActivateAudioInterfaceAsync(deviceID->Data(),__uuidof(IAudioClient2),nullptr,this,&asyncOp));
+
+ }
+
+ ~impl(){
+ audioClient_->Stop();
+ audioRenderClient_.Reset();
+ audioClient_->Reset();
+ };
+
+ void Render()
+ {
+ ::WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
+ uint32_t padding;
+ ThrowIfErr(audioClient_->GetCurrentPadding(&padding));
+ if(!padding)
+ {
+ BYTE* rawBuffer;
+ ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer));
+ ::memcpy(rawBuffer,buffer_[bufferIndex_].get(),bufferByteCount_);
+ audioRenderClient_->ReleaseBuffer(bufferSize_,0);
+ bufferIndex_ = (bufferIndex_ + 1) & 0x1;
+ processBuffer_(buffer_[bufferIndex_],bufferSize_);
+ }
+ }
+
+ void SetProcessBufferFunc(ProcessBufferType&& v)
+ {
+ Stop();
+ processBuffer_ = std::move(v);
+ Start();
+ }
+ void ResetProcessBufferFunc()
+ {
+ Stop();
+ processBuffer_ = std::move(std::bind(&SoundDriver::impl::DefaultProcessBuffer,this,stps::_1,stps::_2));
+ Start();
+ }
+
+ void Start()
+ {
+ if(isStart_) return;
+
+ ThrowIfErr(audioClient_->Start());
+
+ isStart_ = true;
+ }
+
+ void Stop()
+ {
+ if(!isStart_) return;
+
+ ThrowIfErr(audioClient_->Stop());
+
+ isStart_ = false;
+ }
+
+ WAVEFORMATEXTENSIBLE& Format()
+ {
+ return format_;
+ }
+
+ void DefaultProcessBuffer(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;
+ //}
+ }
+
+ // IActivateAudioInterfaceCompletionHandler
+ STDMETHOD(ActivateCompleted)( IActivateAudioInterfaceAsyncOperation *operation )
+ {
+ try {
+ if(!audioClient_)
+ {
+ throw AudioClientNullException(L"\8aù\92è\82ÌAudioClient\82ð\83A\83N\83e\83B\83x\81[\83g\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B");
+ }
+
+
+ } catch (...)
+ {
+ return E_FAIL;
+ }
+ return S_OK;
+ }
+
+ private:
+ ProcessBufferType processBuffer_;
+ IAudioClient2Ptr audioClient_;
+ uint32_t bufferSize_;
+ REFERENCE_TIME latency_;
+ // IAudioClockAdjustmentPtr audioClockAdjustment_;
+ IAudioRenderClientPtr audioRenderClient_;
+ WAVEFORMATEXTENSIBLE format_;
+ sf::handle_holder eventHolder_;
+ boost::shared_array<float> buffer_[2];
+ int bufferIndex_;
+ int bufferByteCount_;
+ bool isStart_;
+
+ };
+
+ SoundDriver::SoundDriver() : impl_(new impl()) {}
+
+ SoundDriver::~SoundDriver()
+ {
+ impl_.reset();
+ }
+
+ void SoundDriver::Render()
+ {
+ impl_->Render();
+ }
+
+ void SoundDriver::SetProcessBufferFunc(ProcessBufferType&& v)
+ {
+ impl_->SetProcessBufferFunc(std::move(v));
+ }
+
+ void SoundDriver::ResetProcessBufferFunc()
+ {
+ impl_->ResetProcessBufferFunc();
+ }
+
+ void SoundDriver::Start()
+ {
+ impl_->Start();
+ }
+
+ void SoundDriver::Stop()
+ {
+ impl_->Stop();
+ }
+
+ WAVEFORMATEXTENSIBLE& SoundDriver::Format()
+ {
+ return impl_->Format();
+ }
+
+}
--- /dev/null
+#pragma once
+#include "WaveTableSynth.h"
+#include "Sequencer.h"
+#include "TestSong.h"
+
+typedef Microsoft::WRL::ComPtr<IAudioClient2> IAudioClient2Ptr;
+//typedef Microsoft::WRL::ComPtr<IAudioClock2> IAudioClock2Ptr;
+typedef Microsoft::WRL::ComPtr<IAudioRenderClient> IAudioRenderClientPtr;
+//typedef Microsoft::WRL::ComPtr<IAudioCaptureClient> IAudioCaptureClientPtr;
+//typedef Microsoft::WRL::ComPtr<IAudioClockAdjustment> IAudioClockAdjustmentPtr;
+
+namespace sf {
+
+ DefineException(AudioClientNull);
+ DefineException(AudioFormatNotSupported);
+
+ struct SoundDriver
+ {
+ typedef std::function<void (boost::shared_array<float> arr,int bufferSize)> ProcessBufferType;
+
+ SoundDriver();
+ ~SoundDriver();
+
+ void Render();
+ void Start();
+ void Stop();
+ void DefaultProcessBuffer(boost::shared_array<float> arr,int bufferSize);
+ void SetProcessBufferFunc(ProcessBufferType&& v);
+ void ResetProcessBufferFunc();
+ WAVEFORMATEXTENSIBLE& Format();
+ private:
+ struct impl;
+ std::unique_ptr<impl> impl_;
+ };
+}
+
--- /dev/null
+#include "pch.h"
+#include "SoundManager.h"
+
+namespace stps = std::placeholders;
+
+namespace sf {
+SoundManager::SoundManager(SoundDriver& driver) : driver_(driver),synth_(driver_.Format()),sequencer_(synth_,driver_.Format())
+{
+ sequencer_.Tempo(150.0f);
+ TestSong song(sequencer_.SequenceTracks());
+ driver_.SetProcessBufferFunc(std::bind(&SoundManager::ProcessBuffer,this,stps::_1,stps::_2));
+}
+
+void SoundManager::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,sizeof(float) * bufferSize * 2);
+
+ for(int i = 0;i < bufferSize;++i)
+ {
+ sequencer_.Process();
+ synth_.Process(ptr);
+ ptr += 2;
+ }
+
+}
+
+
+
+SoundManager::~SoundManager()
+{
+}
+}
--- /dev/null
+#pragma once
+
+#include "SoundDriver.h"
+#include "WaveTableSynth.h"
+#include "Sequencer.h"
+#include "TestSong.h"
+
+namespace sf {
+ struct SoundManager
+ {
+ SoundManager(SoundDriver& driver);
+ void ProcessBuffer(boost::shared_array<float> arr,int bufferSize);
+ virtual ~SoundManager();
+ sf::Synthesizer& SoundManager::Synthesizer() {return synth_;}
+ sf::Sequencer& SoundManager::Sequencer() {return sequencer_;}
+ private:
+ SoundDriver& driver_;
+ sf::Synthesizer synth_;
+ sf::Sequencer sequencer_;
+ };
+}
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{823bbd24-b801-49ee-9763-f8186c389f34}</ProjectGuid>
+ <RootNamespace>SynthApp</RootNamespace>
+ <DefaultLanguage>ja-JP</DefaultLanguage>
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <AppContainerApplication>true</AppContainerApplication>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <PackageCertificateKeyFile>SynthApp_TemporaryKey.pfx</PackageCertificateKeyFile>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="BasicMath.h" />
+ <ClInclude Include="exception.h" />
+ <ClInclude Include="pch.h" />
+ <ClInclude Include="App.xaml.h">
+ <DependentUpon>App.xaml</DependentUpon>
+ </ClInclude>
+ <ClInclude Include="MainPage.xaml.h">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </ClInclude>
+ <ClInclude Include="Sequencer.h" />
+ <ClInclude Include="sf_com.h" />
+ <ClInclude Include="sf_memory.h" />
+ <ClInclude Include="SoundDriver.h" />
+ <ClInclude Include="SoundManager.h" />
+ <ClInclude Include="TestSong.h" />
+ <ClInclude Include="WaveTableSynth.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="Common\StandardStyles.xaml">
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="MainPage.xaml">
+ <SubType>Designer</SubType>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <AppxManifest Include="Package.appxmanifest">
+ <SubType>Designer</SubType>
+ </AppxManifest>
+ <None Include="SynthApp_TemporaryKey.pfx" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="Assets\Logo.png" />
+ <Image Include="Assets\SmallLogo.png" />
+ <Image Include="Assets\StoreLogo.png" />
+ <Image Include="Assets\SplashScreen.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="App.xaml.cpp">
+ <DependentUpon>App.xaml</DependentUpon>
+ </ClCompile>
+ <ClCompile Include="MainPage.xaml.cpp">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </ClCompile>
+ <ClCompile Include="pch.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="Sequencer.cpp" />
+ <ClCompile Include="sf_com.cpp" />
+ <ClCompile Include="SoundDriver.cpp" />
+ <ClCompile Include="SoundManager.cpp" />
+ <ClCompile Include="TestSong.cpp" />
+ <ClCompile Include="WaveTableSynth.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /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();
+ /* for(int i = 0;i < 5;++i){
+ 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_;
+ };
+}
+
--- /dev/null
+#include "pch.h"
+//#include "xbyak\xbyak.h"
+#include "WaveTableSynth.h"
+
+namespace stps = std::placeholders;
+
+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,
+ const GUID& sub_type = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
+ {
+ ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));
+ format.Format.wFormatTag = type;
+ format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+ format.SubFormat = sub_type;
+ format.Format.nSamplesPerSec = sample_rate;
+ format.Format.nChannels = channels;
+ format.Format.wBitsPerSample = bits_per_sample;
+ format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;
+ format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
+ format.Samples.wValidBitsPerSample = valid_bits_per_sample;
+ format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+ }
+
+ void makeWaveFormat(WAVEFORMATEX& format,int sample_rate = 44100,int channels = 2,int bits = 16,uint32_t type = WAVE_FORMAT_PCM)
+ {
+ ZeroMemory(&format,sizeof(WAVEFORMATEX));
+ format.wFormatTag = type;
+ format.nSamplesPerSec = sample_rate;
+ format.nChannels = channels;
+ format.wBitsPerSample = bits;
+ format.nBlockAlign = (format.wBitsPerSample / 8) * format.nChannels;
+ format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
+ };
+
+ void Synthesizer::WaveTableOscillator::WaveTable(Synthesizer::WaveTable *p)
+ {
+ waveTable_ = p;
+ if(waveTable_->stereo)
+ {
+ processor_ = std::bind(&sf::Synthesizer::WaveTableOscillator::ProcessStereo,this,stps::_1,stps::_2,stps::_3);
+ } else {
+ processor_ = std::bind(&sf::Synthesizer::WaveTableOscillator::ProcessMono,this,stps::_1,stps::_2,stps::_3);
+ }
+
+ }
+
+ struct Synthesizer::impl {
+
+ impl(){};
+ explicit impl(WAVEFORMATEXTENSIBLE& format,int channel) : format_(format) ,isEnable_(false)
+ {
+
+ // 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)
+ {
+ voices_.push_back(Voice((float)format.Format.nSamplesPerSec));
+ }
+
+ };
+
+ ~impl(){};
+
+ void Restart(){};
+
+ void Process(float *buffer)
+ {
+ 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;
+ // //}
+ //}
+
+
+ enum struct EnvelopeStatus
+ {
+ None,Attack,Decay,Sustain,Release,End
+ };
+
+ struct EnvelopeController
+ {
+ 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()
+ {
+ status_ = EnvelopeStatus::None;
+ }
+
+ void Init(Envelope * env,float sampleRate)
+ {
+ envelope_ = env;
+ stepTime_ = 1.0f / sampleRate;
+ }
+
+ void Attack()
+ {
+ counter_ = 0.0f;
+ if(envelope_->attackTime == 0.0f)
+ {
+ value_ = 1.0f;
+ return Decay();
+ }
+ status_ = EnvelopeStatus::Attack;
+ delta_ = stepTime_ / envelope_->attackTime;
+ value_ = 0.0f;
+
+ }
+
+ void Decay()
+ {
+ if(envelope_->sustainLevel == 1.0f)
+ {
+ Sustain();
+ }
+ delta_ = (1.0f - envelope_->sustainLevel) * stepTime_ / (envelope_->decayTime);
+ status_ = EnvelopeStatus::Decay;
+ }
+
+ void Sustain()
+ {
+
+ if(envelope_->sustainLevel == 0.0f)
+ {
+ status_ = EnvelopeStatus::End;
+ }
+
+ status_ = EnvelopeStatus::Sustain;
+ }
+
+ void 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:
+ value_ += delta_;
+ if(value_ >= 1.0f)
+ {
+ value_ = 1.0f;
+ Decay();
+ }
+ break;
+ case EnvelopeStatus::Decay:
+ value_ -= delta_;
+ if(value_ <= envelope_->sustainLevel)
+ {
+ value_ = envelope_->sustainLevel;
+ Sustain();
+ }
+ break;
+ case EnvelopeStatus::Sustain:
+ {
+ value_ = envelope_->sustainLevel;
+ }
+ break;
+ case EnvelopeStatus::Release:
+ {
+ value_ -= delta_;
+ if(value_ <= 0.0f)
+ {
+ value_ = 0.0f;
+ status_ = EnvelopeStatus::End;
+ }
+ }
+ break;
+ }
+ return value_ * envelope_->gain;
+ }
+
+ EnvelopeStatus GetStatus()
+ {
+ 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)
+ {
+ };
+
+ 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;
+ }
+
+ sf::Synthesizer::LFO& LFOController::LFO()
+ {
+ 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);
+ }
+
+ float Process()
+ {
+ 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:
+ 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_;
+
+ };
+
+
+
+ struct Voice
+ {
+
+ explicit Voice(float sampleRate)
+ :
+ programNo_(0),
+ noteOn_(false),
+ isFree_(true),
+ pitchOffset_(0.0f),
+ volumeOffset_(1.0f),
+ stepTime_(0.0f),
+ currentTime_(0.0f),
+ curentIndex_(0),
+ pan_(0.5f),
+ sampleRate_(sampleRate),
+ pitchDelta_(0.0f),
+ pitchCounter_(0.0f),
+ waveSize_(0)
+ {};
+
+ Voice(const Voice& 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_),
+ 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 SetProgram(int programNo,Program& program)
+ {
+ 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¤
+ {
+ if(!isFree_){
+
+ //if(pitchCounter_ >= (waveSize_ - 1.0f))
+ //{
+ // pitchCounter_ -= (waveSize_ - 1.0f);
+ //}
+
+ // Wave\82Ì\90¶\90¬
+
+ float waveData[2];
+
+ timber_.oscillator->Process(
+ waveData,
+ pitchDelta_,
+ pitchOffset_
+ + pitchLFO_.Process()
+ + pitchEnv_.Process()
+ + timber_.pitch.pitch );
+
+ // \83t\83B\83\8b\83^\81[\8f\88\97\9d
+
+ float cutoff = timber_.filter.cutoff + filterEnv_.Process() + filterLFO_.Process();
+ filterL_.CutOff(cutoff);
+ filterR_.CutOff(cutoff);
+
+ waveData[0] = filterL_.Process(waveData[0]);
+ waveData[1] = filterR_.Process(waveData[1]);
+
+
+ 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;
+
+ 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];
+ buffer[1] += waveData[1];
+
+ if(!noteOn_ && ampEnv_.GetStatus() == EnvelopeStatus::End)
+ {
+ isFree_ = true;
+ }
+ }
+ }
+
+ bool isFree() {return isFree_;}
+
+ void NoteOn(float pitch,float volume)
+ {
+ if(!noteOn_){
+ isFree_ = false;
+ noteOn_ = true;
+ pitchOffset_ = pitch;
+ volumeOffset_ = volume;
+ stepTime_ = 1.0f / sampleRate_;
+ pitchDelta_ = timber_.oscillator->CalcPitchDelta(sampleRate_);
+ // waveSize_ = (float)osc_->waveData.size();
+ currentTime_ = 0.0f;
+ curentIndex_ = 0;
+ pan_ = timber_.pan.pan;
+ pitchCounter_ = 0.0f;
+ ampEnv_.Attack();
+ filterEnv_.Attack();
+ pitchEnv_.Attack();
+ panEnv_.Attack();
+
+ ampLFO_.Attack();
+ filterLFO_.Attack();
+ pitchLFO_.Attack();
+ panLFO_.Attack();
+
+ filterL_.Start();
+ filterR_.Start();
+ }
+ }
+
+ void NoteOff()
+ {
+ if(noteOn_)
+ {
+ noteOn_ = false;
+ ampEnv_.Release();
+ filterEnv_.Release();
+ pitchEnv_.Release();
+ panEnv_.Release();
+
+ ampLFO_.Release();
+ filterLFO_.Release();
+ pitchLFO_.Release();
+ panLFO_.Release();
+
+ }
+ }
+
+ int CurrentProgramNo() const {return programNo_;}
+
+ private:
+ Timber timber_;
+ int programNo_;
+ bool noteOn_;
+ bool isFree_;
+ float pitchOffset_;
+ float volumeOffset_;
+ float stepTime_;
+ float currentTime_;
+ int curentIndex_;
+ float pan_;
+ float sampleRate_;
+ float pitchDelta_;
+ float pitchCounter_;
+ float waveSize_;
+ // 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();};
+
+ bool isEnable() const {return isEnable_;}
+ void isEnable(bool v) {isEnable_ = v;}
+
+ void Clear()
+ {
+ WaveTable::WaveTables.clear();
+ programs_.clear();
+ }
+
+ private:
+ bool isEnable_;
+ WAVEFORMATEXTENSIBLE format_;
+ ProgramsType programs_;// \83v\83\8a\83Z\83b\83g
+ VoicesType voices_; // Max 64 Voices
+ // WaveTablesType waveTables_;
+ };
+
+ Synthesizer::Synthesizer() : impl_(new Synthesizer::impl()){};
+
+ Synthesizer::Synthesizer(WAVEFORMATEXTENSIBLE& format,int channel ) : impl_(new Synthesizer::impl(format,channel))
+ {
+ }
+
+ Synthesizer::~Synthesizer()
+ {
+
+ }
+
+ //void Synthesizer::ProcessBuffer(boost::shared_array<float> arr,int bufferSize)
+ //{
+ // impl_->ProcessBuffer(arr,bufferSize);
+ //}
+
+ void Synthesizer::Process(float* buffer)
+ {
+ impl_->Process(buffer);
+ }
+
+
+ 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);
+ }
+
+ Synthesizer::WaveTablesType& Synthesizer::WaveTables()
+ {
+ return WaveTable::WaveTables;
+ }
+
+ bool Synthesizer::isEnable() const
+ {
+ return impl_->isEnable();
+
+ }
+ void Synthesizer::isEnable(bool v)
+ {
+ impl_->isEnable(v);
+ }
+
+ void Synthesizer::Clear()
+ {
+ impl_->Clear();
+ }
+
+}
--- /dev/null
+#pragma once
+
+namespace sf {
+ struct Synthesizer
+ {
+ // \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();
+ // \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;
+
+ // \83E\83F\81[\83u\83e\81[\83u\83\8b
+ static WaveTablesType& WaveTables();
+
+ bool isEnable() const ;
+ void isEnable(bool v);
+
+ void Clear();
+
+ private:
+ struct impl;
+ std::unique_ptr<impl> impl_;
+ };
+}
--- /dev/null
+#include "pch.h"
+#include "exception.h"
+#include <objbase.h>
+#include <wtypes.h>
+#include <winerror.h>
+#include <avrt.h>
+#include <strsafe.h>
+#include <audioclient.h>
+#include <audiopolicy.h>
+
+
+
+#define BOOST_ASSIGN_MAX_PARAMS 7
+#include <boost/assign.hpp>
+#include <boost/assign/ptr_list_of.hpp>
+#include <boost/assign/ptr_list_inserter.hpp>
+#include <boost/foreach.hpp>
+
+#if _DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
+#endif
+
+#include "sf_memory.h"
+
+using namespace boost;
+
+namespace sf
+{
+//typedef CComPtr<IAudioClient> IAudioClientPtr;
+std::map<HRESULT,std::wstring> com_error_ = boost::assign::list_of<std::pair<HRESULT,std::wstring> >
+ (E_POINTER,L"E_POINTER")
+ (E_INVALIDARG,L"E_INVALIDARG")
+ (DWRITE_E_FILEFORMAT,L"DWRITE_E_FILEFORMAT")
+ (DWRITE_E_UNEXPECTED,L"DWRITE_E_UNEXPECTED")
+ (DWRITE_E_NOFONT,L"DWRITE_E_NOFONT")
+ (DWRITE_E_FILENOTFOUND,L"DWRITE_E_FILENOTFOUND")
+ (DWRITE_E_FILEACCESS,L"DWRITE_E_FILEACCESS")
+ (DWRITE_E_FONTCOLLECTIONOBSOLETE,L"DWRITE_E_FONTCOLLECTIONOBSOLETE")
+ (DWRITE_E_ALREADYREGISTERED,L"DWRITE_E_ALREADYREGISTERED")
+ (AUDCLNT_E_NOT_INITIALIZED,L"AUDCLNT_E_NOT_INITIALIZED")
+ (AUDCLNT_E_ALREADY_INITIALIZED,L"AUDCLNT_E_ALREADY_INITIALIZED")
+ (AUDCLNT_E_WRONG_ENDPOINT_TYPE,L"AUDCLNT_E_WRONG_ENDPOINT_TYPE")
+ (AUDCLNT_E_DEVICE_INVALIDATED,L"AUDCLNT_E_DEVICE_INVALIDATED")
+ (AUDCLNT_E_NOT_STOPPED,L"AUDCLNT_E_NOT_STOPPED")
+ (AUDCLNT_E_BUFFER_TOO_LARGE,L"AUDCLNT_E_BUFFER_TOO_LARGE")
+ (AUDCLNT_E_OUT_OF_ORDER,L"AUDCLNT_E_OUT_OF_ORDER")
+ (AUDCLNT_E_UNSUPPORTED_FORMAT,L"AUDCLNT_E_UNSUPPORTED_FORMAT")
+ (AUDCLNT_E_INVALID_SIZE,L"AUDCLNT_E_INVALID_SIZE")
+ (AUDCLNT_E_DEVICE_IN_USE,L"AUDCLNT_E_DEVICE_IN_USE")
+ (AUDCLNT_E_BUFFER_OPERATION_PENDING,L"AUDCLNT_E_BUFFER_OPERATION_PENDING")
+ (AUDCLNT_E_THREAD_NOT_REGISTERED,L"AUDCLNT_E_THREAD_NOT_REGISTERED")
+ (AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED,L"AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED")
+ (AUDCLNT_E_ENDPOINT_CREATE_FAILED,L"AUDCLNT_E_ENDPOINT_CREATE_FAILED")
+ (AUDCLNT_E_SERVICE_NOT_RUNNING,L"AUDCLNT_E_SERVICE_NOT_RUNNING")
+ (AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED,L"AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED")
+ (AUDCLNT_E_EXCLUSIVE_MODE_ONLY,L"AUDCLNT_E_EXCLUSIVE_MODE_ONLY")
+ (AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL,L"AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL")
+ (AUDCLNT_E_EVENTHANDLE_NOT_SET,L"AUDCLNT_E_EVENTHANDLE_NOT_SET")
+ (AUDCLNT_E_INCORRECT_BUFFER_SIZE,L"AUDCLNT_E_INCORRECT_BUFFER_SIZE")
+ (AUDCLNT_E_CPUUSAGE_EXCEEDED,L"AUDCLNT_E_CPUUSAGE_EXCEEDED")
+ (AUDCLNT_E_BUFFER_ERROR,L"AUDCLNT_E_BUFFER_ERROR")
+ (AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED,L"AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED")
+ (AUDCLNT_E_BUFFER_SIZE_ERROR,L"AUDCLNT_E_BUFFER_SIZE_ERROR")
+ (AUDCLNT_E_INVALID_DEVICE_PERIOD,L"AUDCLNT_E_INVALID_DEVICE_PERIOD")
+ (AUDCLNT_S_BUFFER_EMPTY,L"AUDCLNT_S_BUFFER_EMPTY")
+ (AUDCLNT_S_THREAD_ALREADY_REGISTERED,L"AUDCLNT_S_THREAD_ALREADY_REGISTERED")
+ (AUDCLNT_S_POSITION_STALLED,L"AUDCLNT_S_POSITION_STALLED")
+ (DXGI_ERROR_UNSUPPORTED,L"DXGI_ERROR_UNSUPPORTED ")
+ (DXGI_STATUS_OCCLUDED,L"DXGI_STATUS_OCCLUDED")
+ (DXGI_STATUS_CLIPPED,L"DXGI_STATUS_CLIPPED")
+ ;
+
+
+win32_error_exception::win32_error_exception(uint32_t hr)
+: std::exception("HRESULT ERROR"),hresult_(hr)
+{
+ local_memory<wchar_t> mem;
+ DWORD 結果 = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hr,0,(LPWSTR)&mem,0,0);
+ if(結果 != 0){
+ error_ = mem.get();
+ } else {
+ std::map<HRESULT,std::wstring>::iterator it = com_error_.find(hr);
+ if(it != com_error_.end())
+ {
+ error_ = it->second;
+ } else {
+ error_ = (boost::wformat(L"0x%x 不明なCOMエラー") % hr).str();
+ }
+#ifdef _DEBUG
+ wdout << L"#### Exception Occured ####" << error_ << std::endl;
+#endif
+ }
+
+};
+
+win32_error_exception::win32_error_exception()
+{
+ hresult_ = ::GetLastError();
+ local_memory<wchar_t> mem;
+ DWORD rv = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,hresult_,0,(LPWSTR)&mem,0,0);
+ error_ = mem.get();
+#ifdef _DEBUG
+ wdout << L"#### Exception Occured ####" << error_ << std::endl;
+#endif
+
+ //Logger::outputDebugPrintf(L"Win32 Error %x %s",hresult_,mem.Get() );
+};
+
+std::wstring win32_error_exception::get_last_error_str(uint32_t err)
+{
+// DWORD err = ::GetLastError();
+ std::wstring err_str;
+ local_memory<wchar_t> mem;
+ DWORD rv = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,err,0,(LPWSTR)&mem,0,0);
+ err_str = mem.get();
+#ifdef _DEBUG
+ wdout << L"#### Exception Occured ####" << err_str << std::endl;
+#endif
+ return err_str;
+}
+
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+
+namespace sf
+{
+ template <typename ExceptionTag> class ExceptionT : public std::exception
+ {
+ public:
+ typedef ExceptionTag tag;
+ explicit ExceptionT(const std::wstring& reason)
+ {
+ m_reason = reason;
+ };
+ const wchar_t * what() {return m_reason.c_str();};
+ const std::wstring& what_str() { return m_reason;};
+ protected:
+ std::wstring m_reason;
+ };
+
+ #define DefineException(x) struct x {}; typedef sf::ExceptionT<x> x## Exception;
+
+ inline void ThrowIfErr(HRESULT hr) {if(hr != S_OK){throw Platform::Exception::CreateException(hr);}}
+
+}
+
--- /dev/null
+//
+// pch.cpp
+// 標準ヘッダーをインクルードし、プリコンパイル済みヘッダーを生成します。
+//
+
+#include "pch.h"
--- /dev/null
+//
+// pch.h
+// 標準システムのインクルード ファイルのヘッダー。
+//
+
+#pragma once
+
+#include <collection.h>
+//
+// pch.h
+// 標準システムのインクルード ファイルのヘッダー。
+//
+
+#pragma once
+
+#include <collection.h>
+#include <wrl.h>
+#include <d3d11_1.h>
+#include <d2d1_1.h>
+#include <d2d1effects.h>
+#include <dwrite_1.h>
+#include <wincodec.h>
+#include <agile.h>
+#include <DirectXMath.h>
+
+#include <xaudio2.h>
+#include <xaudio2fx.h>
+
+#include <mmreg.h>
+#include <mfidl.h>
+#include <mfapi.h>
+#include <mfreadwrite.h>
+
+#include <XInput.h>
+
+#include <stdio.h>
+#include <vector>
+#include <memory>
+
+#include <thread>
+#include <ppltasks.h>
+
+// Core Audio
+#include "avrt.h"
+#include "mmsystem.h"
+#include <mmdeviceapi.h>
+#include <AudioClient.h>
+#include <audiopolicy.h>
+
+
+#include "exception.h"
+#include "strsafe.h"
+
+#include "boost/format.hpp"
+#include "boost/lexical_cast.hpp"
+#include "boost/shared_array.hpp"
+#include "boost/ptr_container/ptr_array.hpp"
+
+#include "sf_com.h"
+#include "sf_memory.h"
+#define COMPTR_TYPEDEF(x) typedef Microsoft::WRL::ComPtr<x> x## Ptr
+#include "windows.ui.xaml.media.dxinterop.h"
+
--- /dev/null
+/*
+ ==============================================================================
+
+ This file is part of the S.F.Tracker
+ Copyright 2005-7 by Satoshi Fujiwara.
+
+ S.F.Tracker can be redistributed and/or modified under the terms of the
+ GNU General Public License, as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later version.
+
+ S.F.Tracker is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ ==============================================================================
+*/
+/** @file
+ * @brief util
+ * @author S.F. (Satoshi Fujiwara)
+ */
+
+#include "pch.h"
+#include <objbase.h>
+#include "sf_com.h"
+namespace sf {
+
+ struct com_initialize::impl
+ {
+ impl(void * reserved,unsigned int init) : hr(::CoInitializeEx(reserved,init))
+ {
+ }
+
+ ~impl()
+ {
+ if(hr == S_OK){
+ ::CoUninitialize();
+ }
+ }
+ private:
+ HRESULT hr;
+ };
+
+ com_initialize::com_initialize(void * reserved,unsigned int init)
+ : m_impl(new com_initialize::impl(reserved,init))
+ {
+ };
+
+ //template <typename ComClass,typename ComInterface> boost::intrusive_ptr<ComInterface> com_creator<ComClass,ComInterface>::create_instance()
+ //{
+ // ComClass * com_ptr;
+ // CoCreateInstance( __uuidof(ComClass), NULL,
+ // CLSCTX_ALL, __uuidof(ComInterface),
+ // (void**)&com_ptr);
+ // return instrusive_ptr<ComClass>(com_ptr,false);
+ //};
+
+
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+/*
+ ==============================================================================
+
+ This file is part of the Shooting3
+ Copyright 2005-11 by Satoshi Fujiwara.
+
+ async can be redistributed and/or modified under the terms of the
+ GNU General Public License, as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later version.
+
+ async is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with async; if not, visit www.gnu.org/licenses or write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ ==============================================================================
+*/
+/** @file
+ * @brief util
+ * @author S.F. (Satoshi Fujiwara)
+ */
+#include "objbase.h"
+
+
+
+namespace sf
+{
+ enum com_init
+ {
+ multi_threaded = 0x0,
+ apartment_threaded = 0x2,
+ disable_ole1dde = 0x4,
+ speed_over_memory = 0x8
+ };
+
+ struct com_initialize
+ {
+ struct impl;
+ com_initialize(void * reserved ,unsigned int init);
+ com_initialize(){com_initialize(0,multi_threaded);};
+ ~com_initialize() {};
+ private:
+ std::shared_ptr<impl> m_impl;
+ };
+
+
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+namespace sf {
+// policy class
+struct heap_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::HeapFree( ::GetProcessHeap(), 0, AMemory );
+}
+};
+// policy class
+struct local_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::LocalFree( AMemory );
+}
+};
+// policy class
+struct co_task_memory_free_policy
+{
+template< typename T >
+void operator()( const T* AMemory ) const
+{
+if( NULL != AMemory )
+::CoTaskMemFree( AMemory );
+}
+};
+// base guard class
+template< typename T,class TFreePolicy >
+class base_memory
+{
+private:
+T *FMemory;
+
+public:
+base_memory( T* AMemory = NULL )
+: FMemory( AMemory ) {}
+
+virtual ~base_memory( void )
+{ reset(); }
+
+T* release( void )
+{
+T *tmp = FMemory;
+FMemory = NULL;
+return tmp;
+}
+
+void reset( T* AMemory = NULL )
+{
+if( AMemory != FMemory )
+{
+if( NULL != FMemory )
+TFreePolicy( FMemory );
+
+FMemory = AMemory;
+}
+}
+
+T* get( void )
+{ return FMemory; }
+
+T* operator ->(void)
+{
+ return FMemory;
+}
+
+T** operator&( void )
+{ return &FMemory; }
+
+};
+template< typename T >
+class heap_memory : public base_memory< T,
+heap_memory_free_policy >
+{
+public:
+heap_memory( T* AMemory = NULL )
+: base_memory< T, heap_memory_free_policy >( AMemory )
+{ }
+};
+template< typename T >
+class local_memory : public base_memory< T,
+local_memory_free_policy >
+{
+public:
+local_memory( T* AMemory = NULL )
+: base_memory< T, local_memory_free_policy >( AMemory )
+{ }
+};
+template< typename T >
+class co_task_memory : public base_memory< T, co_task_memory_free_policy >
+{
+public:
+co_task_memory( T* AMemory = NULL )
+: base_memory< T, co_task_memory_free_policy >( AMemory )
+{ }
+};
+
+struct handle_deleter {
+ typedef HANDLE pointer;
+ void operator ()(HANDLE handle) {
+ if (handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(handle);
+ }
+ }
+};
+
+typedef std::unique_ptr<HANDLE,handle_deleter> handle_holder;
+
+};
+
+template <class COM_SMART_PTR > inline void safe_release(COM_SMART_PTR& ptr)
+{
+if(ptr)
+{
+ ptr.Reset();
+}
+};
+