• R/O
  • SSH
  • HTTPS

cadencii: コミット


コミットメタ情報

リビジョン162 (tree)
日時2009-05-17 23:05:24
作者kbinani

ログメッセージ

(メッセージはありません)

変更サマリ

差分

--- trunk/ScriptImplement/Render As UTAU.cs (revision 161)
+++ trunk/ScriptImplement/Render As UTAU.cs (revision 162)
@@ -167,6 +167,9 @@
167167 string temp_dir = Path.Combine( Path.GetDirectoryName( script ), Path.GetFileNameWithoutExtension( script ) );
168168
169169 #if DEBUG
170+ if ( !Directory.Exists( temp_dir ) ) {
171+ Directory.CreateDirectory( temp_dir );
172+ }
170173 StreamWriter sw = new StreamWriter( Path.Combine( temp_dir, "log.txt" ) );
171174 #endif
172175 // 原音設定を読み込み
--- trunk/utauvsti/utauvsti.cpp (revision 161)
+++ trunk/utauvsti/utauvsti.cpp (revision 162)
@@ -885,7 +885,8 @@
885885 }
886886 int sa_rendered_last = 0; // どこまでレンダリングが済んでいるか。
887887 if( 0 <= m_last_rendered[track] && m_last_rendered[track] < m_events[track].size() ){
888- int ms_rendered_last = m_events[track][m_last_rendered[track]].msActualTime + m_events[track][m_last_rendered[track]].msActualLength - m_events[track][m_last_rendered[track]].Config.msOverlap;
888+ int index = m_last_rendered[track];
889+ int ms_rendered_last = m_events[track][index].msActualTime + m_events[track][index].msActualLength - m_events[track][index].Config.msOverlap;
889890 sa_rendered_last = sa_from_ms( ms_rendered_last );
890891 }
891892 #ifdef _TEST
@@ -896,7 +897,7 @@
896897 while( sa_to > sa_rendered_last && m_last_rendered[track] + 1 < m_events[track].size() ){
897898 m_last_rendered[track] = m_last_rendered[track] + 1;
898899 int last = m_last_rendered[track];
899- // このループ内では,m_events[m_last_rendered]がレンダリングされる
900+ // このループ内では,m_events[m_last_rendered[track]]がレンダリングされる
900901 m_current_singer = m_events[track][last].Program;
901902 if( m_current_singer < 0 || g_singers.size() <= m_current_singer ){
902903 // 範囲外の場合、とりあえず0にして歌わせる
@@ -926,12 +927,12 @@
926927 oss << track << "_" << last << ".wav";
927928 string filename = oss.str();
928929 int mten = oa.msPreUtterance + oa_next.msOverlap - oa_next.msPreUtterance; //先行発声,オーバーラップによって,本来の音符の長さから変化する量
929- double actual_msec = m_events[track][last].msLength + mten;
930+ int actual_msec = m_events[track][last].msLength + mten;
930931 m_events[track][last].msActualLength = actual_msec;
931932 m_events[track][last].Result = path_combine( g_temp_dir, filename );
932933 m_events[track][last].msActualTime = m_events[track][last].msTime - oa.msPreUtterance;
933934 oss.str( "" );
934- oss << (int)(actual_msec + 50); //ここの50は一定?
935+ oss << actual_msec + 50; //ここの50は一定?
935936 string millisec = oss.str();
936937 oss.str( "" );
937938 string flags = m_events[track][last].get_flags() + "L";
@@ -1291,6 +1292,10 @@
12911292 dat.read( wavbuf, buflen );
12921293 int len = dat.gcount();
12931294 if( len <= 0 ){
1295+ dat.close();
1296+#ifdef _TEST
1297+ g_logger << "BAIL-OUT" << endl;
1298+#endif
12941299 goto fillzero;
12951300 }
12961301 int count = 0;
@@ -1310,6 +1315,10 @@
13101315 dat.read( wavbuf, buflen );
13111316 int len = dat.gcount();
13121317 if( len <= 0 ){
1318+ dat.close();
1319+#ifdef _TEST
1320+ g_logger << "BAIL-OUT" << endl;
1321+#endif
13131322 goto fillzero;
13141323 }
13151324 int count = 0;
@@ -1330,6 +1339,10 @@
13301339 dat.read( wavbuf, buflen );
13311340 int len = dat.gcount();
13321341 if( len <= 0 ){
1342+ dat.close();
1343+#ifdef _TEST
1344+ g_logger << "BAIL-OUT" << endl;
1345+#endif
13331346 goto fillzero;
13341347 }
13351348 int count = 0;
@@ -1350,6 +1363,10 @@
13501363 dat.read( wavbuf, buflen );
13511364 int len = dat.gcount();
13521365 if( len <= 0 ){
1366+ dat.close();
1367+#ifdef _TEST
1368+ g_logger << "BAIL-OUT" << endl;
1369+#endif
13531370 goto fillzero;
13541371 }
13551372 int count = 0;
--- trunk/vstidrv3/stdafx.h (revision 161)
+++ trunk/vstidrv3/stdafx.h (revision 162)
@@ -23,7 +23,7 @@
2323 #endif
2424
2525 //#define USE_DOUBLE
26-#define TEST
26+//#define TEST
2727
2828 namespace Boare{ namespace Cadencii{
2929
--- trunk/vstidrv3/vstidrv3.cpp (revision 161)
+++ trunk/vstidrv3/vstidrv3.cpp (revision 162)
@@ -123,13 +123,6 @@
123123 namespace Boare{ namespace Cadencii{
124124
125125 #ifdef __cplusplus_cli
126- void vstidrv::SetFirstBufferWrittenCallback( Boare::Lib::Media::FirstBufferWrittenCallback ^handler ){
127-#ifdef TEST
128- debug::push_log( "vstidrv::SetFirstBufferWrittenCallback" );
129- debug::push_log( " (handler==nullptr)=" + (handler == nullptr) );
130-#endif
131- s_first_buffer_written_callback = handler;
132- }
133126 #else
134127 AEffect *vstidrv::s_aeffect; // 読込んだdllから作成したVOCALOID2の本体。VOCALOID2への操作はs_aeffect->dispatcherで行う
135128 MIDI_EVENT **vstidrv::s_track_events; // 受信したmidiイベントのリスト。s_track_events[0]はvsqのマスタートラックのtempo情報のみを格納
@@ -195,7 +188,7 @@
195188 if( s_track_events ){
196189 delete [] s_track_events;
197190 }
198- waveplay::terminate();
191+// waveplay::terminate();
199192 //TODO: g_hwave_outの終了処理
200193 #ifdef TEST
201194 #ifdef __cplusplus_cli
@@ -372,8 +365,8 @@
372365
373366 g_block_size = block_size;
374367 g_sample_rate = sample_rate;
375- waveplay::init( g_block_size, g_sample_rate );
376- waveplay::set_first_buffer_written_callback( first_buffer_written_callback );
368+// waveplay::init( g_block_size, g_sample_rate );
369+// waveplay::set_first_buffer_written_callback( first_buffer_written_callback );
377370
378371 #ifdef __cplusplus_cli
379372 WCHAR *str = new WCHAR[dll_path->Length + 1];
@@ -568,13 +561,7 @@
568561 int vstidrv::StartRendering(
569562 __int64 total_samples,
570563 double amplify_left,
571- double amplify_right,
572- int error_samples,
573- bool event_enabled,
574- bool direct_play_enabled,
575- array<System::String ^> ^files,
576- double wave_read_offset_seconds,
577- bool mode_infinite
564+ double amplify_right
578565 #else
579566 int vstidrv::StartRendering(
580567 __int64 total_samples,
@@ -663,44 +650,7 @@
663650 #endif
664651
665652 int max_wave_samples = 0;
666- if( direct_play_enabled ){
667-#ifdef __cplusplus_cli
668- int samples = waveplay::on_your_mark( files, (__int64)(wave_read_offset_seconds * g_block_size) );
669- max_wave_samples = samples - (int)(wave_read_offset_seconds * g_block_size);
670-#else
671- int samples = waveplay::on_your_mark( files, num_files, (__int64)(wave_read_offset_seconds * g_block_size) );
672- max_wave_samples = samples - (int)(wave_read_offset_seconds * g_block_size);
673-#endif
674- }
675653 unsigned int total_processed = 0;
676- waveplay::set_error_samples( 0 );
677- if ( error_samples < 0 ) {
678- float *l = new float[-error_samples];
679- float *r = new float[-error_samples];
680- float *out[] = { l, r };
681- try{
682- waveplay::append( out, -error_samples, 0.0, 0.0 );
683- delete [] l;
684- delete [] r;
685- error_samples = 0;
686-#ifdef __cplusplus_cli
687- }catch( Exception ^ex ){
688-#else
689- }catch( string ex ){
690-#endif
691-#ifdef TEST
692-#ifdef __cplusplus_cli
693- Console::WriteLine( ex->ToString() );
694-#else
695- std::cout << ex << std::endl;
696-#endif
697-#endif
698- }
699- }
700- waveplay::set_error_samples( error_samples );
701- /*if( s_direct_play ){
702- waveplay::set_render_finished( false );
703- }*/
704654
705655 MIDI_EVENT* pWork = s_track_events[1];
706656 //int eof_clock = 0;
@@ -742,9 +692,6 @@
742692 delete [] left_ch;
743693 delete [] right_ch;
744694 free_events( lpEvents );
745- if( direct_play_enabled ){
746- waveplay::abort();
747- }
748695 exit_start_rendering();
749696 return FALSE;
750697 }
@@ -882,9 +829,6 @@
882829 delete [] left_ch;
883830 delete [] right_ch;
884831 free_events( lpEvents );
885- if( direct_play_enabled ){
886- waveplay::abort();
887- }
888832 exit_start_rendering();
889833 return FALSE;
890834 }
@@ -913,16 +857,6 @@
913857 }
914858
915859 if ( !iOffset ) {
916- if( direct_play_enabled ){
917-#ifdef TEST
918- Console::Write( "calling waveplay::append..." );
919-#endif
920- waveplay::append( out_buffer, dwFrames, amplify_left, amplify_right );
921-#ifdef TEST
922- Console::WriteLine( " ...done ");
923-#endif
924- }
925- if( event_enabled ){
926860 #ifdef __cplusplus_cli
927861 array<Double> ^send_data_l = gcnew array<Double>( dwFrames );
928862 array<Double> ^send_data_r = gcnew array<Double>( dwFrames );
@@ -945,7 +879,6 @@
945879 #ifdef TEST
946880 Console::WriteLine( " ...done" );
947881 #endif
948- }
949882 total_processed += dwFrames;
950883 } else {
951884 dwDeltaDelay += iOffset;
@@ -971,9 +904,6 @@
971904 while( dwDelta ){
972905 if ( g_cancelRequired ) {
973906 free_events( lpEvents );
974- if( direct_play_enabled ){
975- waveplay::abort();
976- }
977907 exit_start_rendering();
978908 return FALSE;
979909 }
@@ -984,10 +914,6 @@
984914 s_aeffect->processReplacing( s_aeffect, NULL, out_buffer, dwFrames );
985915 #endif
986916
987- if( direct_play_enabled ){
988- waveplay::append( out_buffer, dwFrames, amplify_left, amplify_right );
989- }
990- if( event_enabled ){
991917 #ifdef __cplusplus_cli
992918 array<Double> ^send_data_l = gcnew array<Double>( dwFrames );
993919 array<Double> ^send_data_r = gcnew array<Double>( dwFrames );
@@ -1004,7 +930,6 @@
1004930 #else
1005931 s_wave_incoming_callback( send_data_l, send_data_r, dwFrames );
1006932 #endif
1007- }
1008933
1009934 dwDelta -= dwFrames;
1010935 total_processed += dwFrames;
@@ -1019,33 +944,8 @@
1019944 std::cout << "vstidrv::StartRendering; total_processed=" << total_processed << std::endl;
1020945 #endif
1021946 #endif
1022- if( direct_play_enabled ){
1023- if( total_processed < max_wave_samples ){
1024- // 同時再生するWAVEファイルのほうが、レンダリング結果より長い場合。同時再生するWAVEファイルが再生し終わるまで無音を挿入する
1025- int remain = max_wave_samples - total_processed;
1026- while( remain > 0 && !g_cancelRequired ){
1027- int delta = (remain > g_block_size) ? g_block_size : remain;
1028- waveplay::append( out_buffer, delta, 0.0, 0.0 );
1029- remain -= delta;
1030- }
1031- }
1032- if( !mode_infinite ){
1033- waveplay::flush_and_exit( amplify_left, amplify_right );
1034- }
1035- }
1036-
1037947 free_events( lpEvents );
1038948
1039- if( direct_play_enabled ){
1040- if( mode_infinite ){
1041- while( !g_cancelRequired ){
1042- waveplay::append( out_buffer, g_block_size, 0.0, 0.0 );
1043- }
1044- }else{
1045- while( waveplay::is_alive() && !g_cancelRequired );
1046- }
1047- }
1048-
1049949 delete [] left_ch;
1050950 delete [] right_ch;
1051951 #ifdef __cplusplus_cli
@@ -1065,74 +965,13 @@
1065965
1066966 void vstidrv::AbortRendering(){
1067967 g_cancelRequired = true;
1068- waveplay::abort();
968+// waveplay::abort();
1069969 };
1070970
1071971 double vstidrv::GetProgress(){
1072972 return g_progress;
1073973 };
1074-
1075- float vstidrv::GetPlayTime(){
1076- return waveplay::get_play_time();
1077- };
1078974
1079- void vstidrv::WaveOutReset(){
1080-#ifdef TEST
1081-#ifdef __cplusplus_cli
1082- Console::WriteLine( "vstidrv::WaveOutReset()" );
1083-#else
1084- std::cout << "vstidrv::WaveOutReset()" << std::endl;
1085-#endif
1086-#endif
1087- waveplay::reset();
1088- };
1089-
1090- int vstidrv::JoyInit(){
1091- return winmmhelp::Init();
1092- };
1093-
1094- bool vstidrv::JoyIsJoyAttatched( int index ){
1095- return winmmhelp::IsJoyAttatched( index );
1096- };
1097-
1098-#ifdef __cplusplus_cli
1099- bool vstidrv::JoyGetStatus( int index, [System::Runtime::InteropServices::Out] array<Byte> ^%buttons, [System::Runtime::InteropServices::Out] int %pov ){
1100-#else
1101- bool vstidrv::JoyGetStatus( int index, unsigned char *buttons, int *pov ){
1102-#endif
1103- int pov_;
1104- int num = winmmhelp::GetNumButtons( index );
1105- unsigned char *buf = new unsigned char[num];
1106- bool ret = winmmhelp::GetStatus( index, buf, num, &pov_ );
1107-#ifdef __cplusplus_cli
1108- buttons = gcnew array<Byte>( num );
1109-#else
1110- buttons = new unsigned char[num];
1111-#endif
1112- for( int i = 0; i < num; i++ ){
1113- buttons[i] = buf[i];
1114- }
1115- delete [] buf;
1116-#ifdef __cplusplus_cli
1117- pov = pov_;
1118-#else
1119- *pov = pov_;
1120-#endif
1121- return ret;
1122- };
1123-
1124- int vstidrv::JoyGetNumButtons( int index ){
1125- return winmmhelp::GetNumButtons( index );
1126- };
1127-
1128- void vstidrv::JoyReset(){
1129- winmmhelp::Reset();
1130- };
1131-
1132- int vstidrv::JoyGetNumJoyDev(){
1133- return winmmhelp::GetNumJoyDev();
1134- };
1135-
1136975 vstidrv::vstidrv(){
1137976 #ifdef TEST
1138977 #ifdef __cplusplus_cli
--- trunk/vstidrv3/waveplay.cpp (revision 161)
+++ trunk/vstidrv3/waveplay.cpp (revision 162)
@@ -247,12 +247,6 @@
247247 float aright = (float)amp_right;
248248 float aleft = (float)amp_left;
249249
250- /*while( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) == WHDR_INQUEUE ){
251- if( s_abort_required ){
252- s_abort_required = false;
253- goto clean_and_exit;
254- }
255- }*/
256250 for( int j = 0; j < jmax; j++ ){
257251 s_wave_buffer_l[j + s_buffer_loc] = data[1][j];
258252 s_wave_buffer_r[j + s_buffer_loc] = data[0][j];
@@ -308,24 +302,6 @@
308302 }
309303
310304 if( remain > 0 ){
311-#ifdef TEST
312- //debug::push_log( "append_cor; waiting(2) " + s_current_buffer + "..." );
313-#endif
314- //while( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) == WHDR_INQUEUE ){
315- /*while( !s_done[s_current_buffer] ){
316-#ifdef TEST
317- for( int k = 0; k < _NUM_BUF; k++ ){
318- //debug::push_log( "append_cor; " + s_done[k] );
319- }
320-#endif
321- if( s_abort_required ){
322- s_abort_required = false;
323- goto clean_and_exit;
324- }
325- }*/
326-#ifdef TEST
327- //debug::push_log( "append_cor; ...exit" );
328-#endif
329305 for( int j = jmax; j < length; j++ ){
330306 s_wave_buffer_l[j - jmax] = data[1][j];
331307 s_wave_buffer_r[j - jmax] = data[0][j];
--- trunk/vstidrv3/vstidrv3.h (revision 161)
+++ trunk/vstidrv3/vstidrv3.h (revision 162)
@@ -15,7 +15,7 @@
1515 #define __vstidrv3_h__
1616 #include "stdafx.h"
1717 #include "winmmhelp.h"
18-#include "waveplay.h"
18+//#include "waveplay.h"
1919 #include "pluginterfaces/vst2.x/aeffectx.h"
2020
2121 #ifdef __cplusplus_cli
@@ -159,7 +159,7 @@
159159 #ifdef __cplusplus_cli
160160 virtual event WaveIncomingEventHandler ^WaveIncoming;
161161 virtual event RenderingFinishedEventHandler ^RenderingFinished;
162- virtual void SetFirstBufferWrittenCallback( Boare::Lib::Media::FirstBufferWrittenCallback ^handler );
162+ //virtual void SetFirstBufferWrittenCallback( Boare::Lib::Media::FirstBufferWrittenCallback ^handler );
163163 #else
164164 static void SetFirstBufferWrittenCallback( FirstBufferWrittenCallback proc );
165165 static void SetWaveIncomingCallback( WaveIncomingCallback proc );
@@ -179,13 +179,7 @@
179179 virtual int StartRendering(
180180 __int64 total_samples,
181181 double amplify_left,
182- double amplify_right,
183- int error_samples,
184- bool event_enabled,
185- bool direct_play_enabled,
186- array<System::String ^> ^files,
187- double wave_read_offset_seconds,
188- bool mode_infinite );
182+ double amplify_right );
189183 #else
190184 static int StartRendering(
191185 __int64 total_samples,
@@ -200,32 +194,8 @@
200194 bool mode_infinite );
201195 #endif
202196 __PFX_INTERFACE__ void AbortRendering();
203- __PFX_INTERFACE__ double GetProgress();
204- __PFX_INTERFACE__ float GetPlayTime();
205- __PFX_INTERFACE__ void WaveOutReset();
197+ __PFX_INTERFACE__ double GetProgress();
206198 __PFX_INTERFACE__ void Terminate();
207-
208- // 初期化。戻り値は、接続されているゲームパッドの個数
209- __PFX_INTERFACE__ int JoyInit();
210- // 第index番目のゲームパッドが接続されているかどうかを調べる
211- __PFX_INTERFACE__ bool JoyIsJoyAttatched( int index );
212- // 第index番目のゲームパッドの状態を取得する。
213-#ifdef __cplusplus_cli
214- virtual bool JoyGetStatus(
215- int index,
216- [System::Runtime::InteropServices::Out] array<Byte> ^%buttons,
217- [System::Runtime::InteropServices::Out] int %pov );
218-#else
219- static bool JoyGetStatus(
220- int index,
221- unsigned char *buttons,
222- int *pov );
223-#endif
224- // 第index番目のゲームパッドが認識できるボタンの個数を取得する。
225- __PFX_INTERFACE__ int JoyGetNumButtons( int index );
226- // リセット。
227- __PFX_INTERFACE__ void JoyReset();
228- __PFX_INTERFACE__ int JoyGetNumJoyDev();
229199 };
230200
231201 } }
--- trunk/Cadencii/AppManager.cs (revision 161)
+++ trunk/Cadencii/AppManager.cs (revision 162)
@@ -22,6 +22,7 @@
2222 using System.Xml.Serialization;
2323 using System.CodeDom.Compiler;
2424 using Microsoft.CSharp;
25+using System.Text;
2526
2627 using Boare.Lib.Vsq;
2728 /*
@@ -60,6 +61,8 @@
6061 /// AttachedCurve用のシリアライザ
6162 /// </summary>
6263 public static XmlSerializer XmlSerializerListBezierCurves = new XmlSerializer( typeof( AttachedCurve ) );
64+ public static string PathResampler = "";
65+ public static string PathWavtool = "";
6366
6467 #region Static Readonly Fields
6568 public static readonly Color[] s_HILIGHT = new Color[] {
@@ -115,7 +118,7 @@
115118 private static SolidBrush s_hilight_brush = new SolidBrush( Color.CornflowerBlue );
116119 private static object s_locker;
117120 private static Boare.Lib.AppUtil.XmlSerializeWithDescription s_serizlizer = null;
118- private static UtauSingerConfigSys s_utau_singers;
121+ public static UtauSingerConfigSys UtauSingers;
119122 #endregion
120123
121124 public delegate void MainFormClosedEventHandler( EditorManager manager );
@@ -522,18 +525,27 @@
522525 }
523526 }
524527 if ( EditorConfig.PathUtauVSTi != "" ) {
525- s_utau_singers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
528+ UtauSingers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
529+ // utauvsti.confを読む
530+ string pathconf = Path.Combine( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ), "utauvsti.conf" );
531+ if ( File.Exists( pathconf ) ) {
532+ using ( StreamReader sr = new StreamReader( pathconf, Encoding.GetEncoding( 0 ) ) ) {
533+ string version = sr.ReadLine();
534+ PathResampler = sr.ReadLine();
535+ PathWavtool = sr.ReadLine();
536+ }
537+ }
526538 } else {
527- s_utau_singers = null;
539+ UtauSingers = null;
528540 }
529541 }
530542
531543 public static Dictionary<int, SingerConfig> getSingerConfigsUtau(){
532- if ( s_utau_singers == null && EditorConfig.PathUtauVSTi != "" ) {
533- s_utau_singers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
544+ if ( UtauSingers == null && EditorConfig.PathUtauVSTi != "" ) {
545+ UtauSingers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
534546 }
535- if ( s_utau_singers != null ) {
536- return s_utau_singers.getSingerConfigs();
547+ if ( UtauSingers != null ) {
548+ return UtauSingers.getSingerConfigs();
537549 } else {
538550 return new Dictionary<int, SingerConfig>();
539551 }
@@ -540,11 +552,11 @@
540552 }
541553
542554 public static VsqID getSingerIDUtau( int program_change ){
543- if ( s_utau_singers == null && EditorConfig.PathUtauVSTi != "" ) {
544- s_utau_singers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
555+ if ( UtauSingers == null && EditorConfig.PathUtauVSTi != "" ) {
556+ UtauSingers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
545557 }
546- if ( s_utau_singers != null ) {
547- return s_utau_singers.getSingerID( program_change );
558+ if ( UtauSingers != null ) {
559+ return UtauSingers.getSingerID( program_change );
548560 } else {
549561 VsqID ret = new VsqID( 0 );
550562 ret.IconHandle = new IconHandle();
@@ -558,11 +570,11 @@
558570 }
559571
560572 public static SingerConfig getSingerInfoUtau( int program_change ) {
561- if ( s_utau_singers == null && EditorConfig.PathUtauVSTi != "" ) {
562- s_utau_singers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
573+ if ( UtauSingers == null && EditorConfig.PathUtauVSTi != "" ) {
574+ UtauSingers = new UtauSingerConfigSys( Path.GetDirectoryName( EditorConfig.PathUtauVSTi ) );
563575 }
564- if ( s_utau_singers != null ) {
565- return s_utau_singers.getSingerInfo( program_change );
576+ if ( UtauSingers != null ) {
577+ return UtauSingers.getSingerInfo( program_change );
566578 } else {
567579 return null;
568580 }
--- trunk/Cadencii/PlaySound.cs (nonexistent)
+++ trunk/Cadencii/PlaySound.cs (revision 162)
@@ -0,0 +1,62 @@
1+using System;
2+using System.Runtime.InteropServices;
3+
4+namespace Boare.Cadencii {
5+
6+ static class PlaySound {
7+ [DllImport( "PlaySound.dll" )]
8+ private static extern void SoundInit( int block_size, int sample_rate );
9+
10+ [DllImport( "PlaySound.dll" )]
11+ private static extern unsafe void SoundAppend( double* left, double* right, int length );
12+
13+ [DllImport( "PlaySound.dll" )]
14+ private static extern void SoundWaitForExit();
15+
16+ [DllImport( "PlaySound.dll" )]
17+ private static extern double SoundGetPosition();
18+
19+ [DllImport( "PlaySound.dll" )]
20+ private static extern bool SoundIsBusy();
21+
22+ [DllImport( "PlaySound.dll" )]
23+ private static extern void SoundReset();
24+
25+ public static void Init( int block_size, int sample_rate ) {
26+ try {
27+ SoundInit( block_size, sample_rate );
28+ } catch {
29+ }
30+ }
31+
32+ public static unsafe void Append( double* left, double* right, int length ) {
33+ try {
34+#if DEBUG
35+ Console.WriteLine( "calling SoundAppend..." );
36+#endif
37+ SoundAppend( left, right, length );
38+#if DEBUG
39+ Console.WriteLine( "...done" );
40+#endif
41+ } catch {
42+ }
43+ }
44+
45+ public static double GetPosition() {
46+ double ret = -1;
47+ try {
48+ ret = SoundGetPosition();
49+ } catch {
50+ }
51+ return ret;
52+ }
53+
54+ public static void Reset() {
55+ try {
56+ SoundReset();
57+ } catch {
58+ }
59+ }
60+ }
61+
62+}
--- trunk/Cadencii/RenderUtau.cs (nonexistent)
+++ trunk/Cadencii/RenderUtau.cs (revision 162)
@@ -0,0 +1,518 @@
1+using System;
2+using System.Collections.Generic;
3+using System.IO;
4+using System.Windows.Forms;
5+using System.Threading;
6+using System.Diagnostics;
7+
8+using bocoree;
9+using Boare.Lib.Vsq;
10+
11+namespace Boare.Cadencii {
12+
13+ public static class RenderUtau {
14+ private static List<Phon> s_resampler_queue = new List<Phon>();
15+ /// <summary>
16+ /// s_resampler_queueの位置
17+ /// </summary>
18+ private static int s_index = -1;
19+ private static bool s_abort_required = false;
20+
21+ public static event WaveIncomingEventHandler WaveIncoming;
22+
23+ class Phon {
24+ public string Lyric;
25+ public string FileName;
26+ public int ClockLength;
27+ public float Tempo;
28+ public bool ModeR;
29+ public OtoArgs Oto;
30+ public UstEvent Event;
31+ public string Note;
32+ public int msDuration;
33+ public bool ResamplFinished;
34+ public double secTime;
35+ public string SingerDir;
36+ public Phon( string lyric, string file_name, int clock_length, float tempo, bool mode_r, OtoArgs oto, UstEvent ev, string note, int ms_duration, double sec_time, string singer_dir ) {
37+ Lyric = lyric;
38+ FileName = file_name;
39+ ClockLength = clock_length;
40+ Tempo = tempo;
41+ ModeR = mode_r;
42+ Oto = oto;
43+ Event = ev;
44+ Note = note;
45+ msDuration = ms_duration;
46+ ResamplFinished = false;
47+ secTime = sec_time;
48+ SingerDir = singer_dir;
49+ }
50+ }
51+
52+ /// <summary>
53+ /// 原音設定の引数.
54+ /// </summary>
55+ struct OtoArgs {
56+ /// <summary>
57+ /// 第1引数.空文字なので使わない
58+ /// </summary>
59+ public string Alias;
60+ public int msOffset;
61+ public int msConsonant;
62+ public int msBlank;
63+ public int msPreUtterance;
64+ public int msOverlap;
65+ }
66+
67+ public static void AbortRendering() {
68+ s_abort_required = true;
69+ }
70+
71+ public static void StartRendering(
72+ VsqFile vsq,
73+ int track,
74+ UtauSingerConfigSys singer_config_sys,
75+ string resampler,
76+ string wavtool,
77+ string temp_dir,
78+ bool invoke_with_wine,
79+ int sample_rate ) {
80+ try {
81+ s_abort_required = false;
82+ if ( !Directory.Exists( temp_dir ) ) {
83+ Directory.CreateDirectory( temp_dir );
84+ }
85+#if DEBUG
86+ //StreamWriter sw = new StreamWriter( Path.Combine( temp_dir, "log.txt" ) );
87+#endif
88+ // 原音設定を読み込み
89+ Dictionary<int, Dictionary<string, OtoArgs>> config = new Dictionary<int, Dictionary<string, OtoArgs>>();
90+ Dictionary<int, SingerConfig> singers = singer_config_sys.getSingerConfigs();
91+ foreach ( int pc in singers.Keys ) {
92+ string singer_name = singers[pc].VOICENAME;
93+ string singer_path = singers[pc].VOICEIDSTR;
94+ string config_file = Path.Combine( singer_path, "oto.ini" );
95+ Dictionary<string, OtoArgs> list = new Dictionary<string, OtoArgs>();
96+ if ( File.Exists( config_file ) ) {
97+ using ( cp932reader sr = new cp932reader( config_file ) ) {
98+ string line;
99+ while ( sr.Peek() >= 0 ) {
100+ line = sr.ReadLine();
101+ string[] spl = line.Split( '=' );
102+ string a1 = spl[0];
103+ string a2 = spl[1];
104+ int index = a1.IndexOf( ".wav" );
105+ a1 = a1.Substring( 0, index );
106+ spl = a2.Split( ',' );
107+ OtoArgs oa = new OtoArgs();
108+ oa.Alias = spl[0];
109+ oa.msOffset = int.Parse( spl[1] );
110+ oa.msConsonant = int.Parse( spl[2] );
111+ oa.msBlank = int.Parse( spl[3] );
112+ oa.msPreUtterance = int.Parse( spl[4] );
113+ oa.msOverlap = int.Parse( spl[5] );
114+ list.Add( a1, oa );
115+ }
116+ }
117+ }
118+ config.Add( pc, list );
119+ }
120+
121+ string filebase = "temp.wav";
122+ string file = Path.Combine( temp_dir, filebase );
123+ if ( File.Exists( file ) ) {
124+ File.Delete( file );
125+ }
126+ string file_whd = Path.Combine( temp_dir, filebase + ".whd" );
127+ if ( File.Exists( file_whd ) ) {
128+ File.Delete( file_whd );
129+ }
130+ string file_dat = Path.Combine( temp_dir, filebase + ".dat" );
131+ if ( File.Exists( file_dat ) ) {
132+ File.Delete( file_dat );
133+ }
134+
135+ int count = -1;
136+ double sec_end = 0;
137+ double sec_end_old = 0;
138+ int program_change = 0;
139+ for ( Iterator itr = vsq.Track[track].getEventIterator(); itr.hasNext(); ) {
140+ VsqEvent item = (VsqEvent)itr.next();
141+ if ( item.ID.type == VsqIDType.Singer ) {
142+ program_change = item.ID.IconHandle.Program;
143+ continue;
144+ } else if ( item.ID.type == VsqIDType.Unknown ) {
145+ continue;
146+ }
147+ if ( s_abort_required ) {
148+ return;
149+ }
150+ count++;
151+ double sec_start = vsq.getSecFromClock( item.Clock );
152+ sec_end_old = sec_end;
153+ sec_end = vsq.getSecFromClock( item.Clock + item.ID.Length );
154+ float t_temp = (float)(item.ID.Length / (sec_end - sec_start) / 8.0);
155+ if ( (count == 0 && sec_start > 0.0) || (sec_start > sec_end_old) ) {
156+ double sec_start2 = sec_end_old;
157+ double sec_end2 = sec_start;
158+ float t_temp2 = (float)(item.Clock / (sec_end2 - sec_start2) / 8.0);
159+ string singer = "";
160+ if ( singers.ContainsKey( program_change ) ) {
161+ singer = singers[program_change].VOICEIDSTR;
162+ }
163+ s_resampler_queue.Add( new Phon( "R",
164+ Path.Combine( singer, "R.wav" ),
165+ item.Clock,
166+ t_temp2,
167+ true,
168+ new OtoArgs(),
169+ new UstEvent(),
170+ "C4",
171+ (int)(sec_end2 - sec_start2),
172+ sec_start2,
173+ singer ) );
174+ count++;
175+ }
176+ string lyric = item.ID.LyricHandle.L0.Phrase;
177+ string note = NoteStringFromNoteNumber( item.ID.Note );
178+ int millisec = (int)((sec_end - sec_start) * 1000) + 50;
179+
180+ //4_あ_C#4_550.wav
181+ string filename = Path.Combine( temp_dir, count + "_" + item.ID.Note + "_" + millisec + ".wav" );
182+ if ( File.Exists( filename ) ) {
183+ File.Delete( filename );
184+ }
185+
186+ OtoArgs oa = new OtoArgs();
187+ if ( config.ContainsKey( program_change ) && config[program_change].ContainsKey( lyric ) ) {
188+ oa = config[program_change][lyric];
189+ }
190+ string singer2 = "";
191+ if ( singers.ContainsKey( program_change ) ) {
192+ singer2 = singers[program_change].VOICEIDSTR;
193+ }
194+ oa.msPreUtterance = item.UstEvent.PreUtterance;
195+ oa.msOverlap = item.UstEvent.VoiceOverlap;
196+ Phon tp = new Phon( lyric, filename, item.ID.Length, t_temp, false, oa, item.UstEvent, note, millisec, sec_start, singer2 );
197+ s_resampler_queue.Add( tp );
198+ }
199+
200+ int num_queues = s_resampler_queue.Count;
201+
202+ // resampler用のスレッドを起動
203+ string[] arg = new string[] { resampler, temp_dir, (invoke_with_wine ? "true" : "false") };
204+ Thread resampl = new Thread( new ParameterizedThreadStart( ResamplerProc ) );
205+ resampl.Priority = ThreadPriority.BelowNormal;
206+ resampl.Start( arg );
207+
208+ int processed_sample = 0; //WaveIncomingで受け渡した波形の合計サンプル数
209+ int channel = 0; // .whdに記録されたチャンネル数
210+ int byte_per_sample = 0;
211+ // このスレッドは引き続き、wavtoolを呼ぶ作業に移行
212+ bool first = true;
213+ for ( int i = 0; i < num_queues; i++ ) {
214+ // resamplerが終了するのを待機
215+ while ( true ) {
216+ if ( s_abort_required ) {
217+ resampl.Abort();
218+ return;
219+ }
220+ if ( s_resampler_queue[i].ResamplFinished ) {
221+ break;
222+ }
223+ Application.DoEvents();
224+ }
225+
226+ // wavtoolを起動
227+ double sec_fin; // 今回のwavtool起動によってレンダリングが完了したサンプル長さ
228+ Phon p = s_resampler_queue[i];
229+ UstEnvelope env = p.Event.Envelope;
230+ if ( env == null ) {
231+ env = new UstEnvelope();
232+ }
233+ OtoArgs oa_next;
234+ if ( i + 1 < num_queues ) {
235+ oa_next = s_resampler_queue[i + 1].Oto;
236+ } else {
237+ oa_next = new OtoArgs();
238+ }
239+ sec_fin = p.secTime + (p.msDuration - oa_next.msOverlap) / 1000.0;
240+ ProcessWavtool( p, env, oa_next, filebase, temp_dir, wavtool, invoke_with_wine );
241+
242+ // できたwavを読み取ってWaveIncomingイベントを発生させる
243+ int sample_end = (int)(sec_fin * sample_rate);
244+#if DEBUG
245+ Common.DebugWriteLine( "RenderUtau.StartRendering; sample_end=" + sample_end );
246+#endif
247+ // whdを読みに行く
248+ if ( first ) {
249+ using ( FileStream whd = new FileStream( file_whd, FileMode.Open, FileAccess.Read ) ) {
250+ whd.Seek( 0, SeekOrigin.Begin );
251+ // RIFF
252+ byte[] buf = new byte[4];
253+ int gcount = whd.Read( buf, 0, 4 );
254+ if ( buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' ) {
255+#if DEBUG
256+ Common.DebugWriteLine( "RenderUtau.startRendering; whd header error" );
257+ Common.DebugWriteLine( ((char)buf[0]).ToString() + "" + ((char)buf[1]).ToString() + "" + ((char)buf[2]).ToString() + "" + ((char)buf[3]).ToString() + " must be RIFF" );
258+#endif
259+ continue;
260+ }
261+ // ファイルサイズ
262+ whd.Read( buf, 0, 4 );
263+ // WAVE
264+ whd.Read( buf, 0, 4 );
265+ if ( buf[0] != 'W' || buf[1] != 'A' || buf[2] != 'V' || buf[3] != 'E' ) {
266+#if DEBUG
267+ Common.DebugWriteLine( "RenderUtau.startRendering; whd header error" );
268+ Common.DebugWriteLine( ((char)buf[0]).ToString() + "" + ((char)buf[1]).ToString() + "" + ((char)buf[2]).ToString() + "" + ((char)buf[3]).ToString() + " must be WAVE" );
269+#endif
270+ continue;
271+ }
272+ // fmt
273+ whd.Read( buf, 0, 4 );
274+ if ( buf[0] != 'f' || buf[1] != 'm' || buf[2] != 't' || buf[3] != ' ' ) {
275+#if DEBUG
276+ Common.DebugWriteLine( "RenderUtau.startRendering; whd header error" );
277+ Common.DebugWriteLine( ((char)buf[0]).ToString() + "" + ((char)buf[1]).ToString() + "" + ((char)buf[2]).ToString() + "" + ((char)buf[3]).ToString() + " must be fmt " );
278+#endif
279+ continue;
280+ }
281+ // fmt チャンクのサイズ
282+ whd.Read( buf, 0, 4 );
283+ long loc_end_of_fmt = whd.Position; //fmtチャンクの終了位置.ここは一定値でない可能性があるので読込み
284+ loc_end_of_fmt += buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
285+ // format ID
286+ whd.Read( buf, 0, 2 );
287+ int id = buf[0] | buf[1] << 8;
288+ if ( id != 0x0001 ) { //0x0001はリニアPCM
289+ continue;
290+ }
291+ // チャンネル数
292+ whd.Read( buf, 0, 2 );
293+ channel = buf[1] << 8 | buf[0];
294+ // サンプリングレート
295+ whd.Read( buf, 0, 4 );
296+ int this_sample_rate = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
297+ // データ速度
298+ whd.Read( buf, 0, 4 );
299+ // ブロックサイズ
300+ whd.Read( buf, 0, 2 );
301+ // 1チャンネル、1サンプルあたりのビット数
302+ whd.Read( buf, 0, 2 );
303+ int bit_per_sample = buf[1] << 8 | buf[0];
304+ byte_per_sample = bit_per_sample / 8;
305+ whd.Seek( loc_end_of_fmt, SeekOrigin.Begin );
306+ // data
307+ whd.Read( buf, 0, 4 );
308+ if ( buf[0] != 'd' || buf[1] != 'a' || buf[2] != 't' || buf[3] != 'a' ) {
309+#if DEBUG
310+ Common.DebugWriteLine( "RenderUtau.startRendering; whd header error" );
311+ Common.DebugWriteLine( ((char)buf[0]).ToString() + "" + ((char)buf[1]).ToString() + "" + ((char)buf[2]).ToString() + "" + ((char)buf[3]).ToString() + " must be data" );
312+#endif
313+ continue;
314+ }
315+ // size of data chunk
316+ whd.Read( buf, 0, 4 );
317+ int size = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
318+ int total_samples = size / (channel * byte_per_sample);
319+ }
320+ first = false;
321+ }
322+
323+ // datを読みに行く
324+ int sampleFrames = sample_end - processed_sample;
325+#if DEBUG
326+ Common.DebugWriteLine( "RenderUtau.StartRendering; sampleFrames=" + sampleFrames + "; channel=" + channel + "; byte_per_sample=" + byte_per_sample );
327+#endif
328+ if ( channel > 0 && byte_per_sample > 0 && sampleFrames > 0 && WaveIncoming != null ) {
329+ int length = sampleFrames;// (sampleFrames > sample_rate ? sample_rate : sampleFrames);
330+ //int remain = sampleFrames;
331+ double[] left = new double[length];
332+ double[] right = new double[length];
333+ const float k_inv64 = 1.0f / 64.0f;
334+ const float k_inv32768 = 1.0f / 32768.0f;
335+ const int buflen = 1024;
336+ byte[] wavbuf = new byte[buflen];
337+ int pos = 0;
338+ using ( FileStream dat = new FileStream( file_dat, FileMode.Open, FileAccess.Read ) ) {
339+ dat.Seek( processed_sample * channel * byte_per_sample, SeekOrigin.Begin );
340+ double ms_start = processed_sample / (double)sample_rate * 1000.0;
341+ double ms_per_sa = 1000.0 / (double)sample_rate;
342+ #region チャンネル数/ビット深度ごとの読み取り操作
343+ if ( byte_per_sample == 1 ) {
344+ if ( channel == 1 ) {
345+ while ( pos < sampleFrames ) {
346+ int len = dat.Read( wavbuf, 0, buflen );
347+ if ( len <= 0 ) {
348+ break;
349+ }
350+ int c = 0;
351+ while ( len > 0 && pos < sampleFrames ) {
352+ double gtime_dyn = ms_start + pos * ms_per_sa;
353+ int dyn = 64;// m_dynamics[track].get_value( gtime_dyn );
354+ float amp = (float)dyn * k_inv64;
355+ float v = (wavbuf[c++] - 64.0f) * k_inv64 * amp;
356+ left[pos] += v;
357+ right[pos] += v;
358+ len -= 1;
359+ pos++;
360+ }
361+ }
362+ } else {
363+ while ( pos < sampleFrames ) {
364+ int len = dat.Read( wavbuf, 0, buflen );
365+ if ( len <= 0 ) {
366+ break;
367+ }
368+ int c = 0;
369+ while ( len > 0 && pos < sampleFrames ) {
370+ double gtime_dyn = ms_start + pos * ms_per_sa;
371+ int dyn = 64;//m_dynamics[track].get_value( gtime_dyn );
372+ float amp = (float)dyn * k_inv64;
373+ left[pos] += (wavbuf[c++] - 64.0f) * k_inv64 * amp;
374+ right[pos] += (wavbuf[c++] - 64.0f) * k_inv64 * amp;
375+ len -= 2;
376+ pos++;
377+ }
378+ }
379+ }
380+ } else if ( byte_per_sample == 2 ) {
381+ if ( channel == 1 ) {
382+ while ( pos < sampleFrames ) {
383+ int len = dat.Read( wavbuf, 0, buflen );
384+ if ( len <= 0 ) {
385+ break;
386+ }
387+ int c = 0;
388+ while ( len > 0 && pos < sampleFrames ) {
389+ double gtime_dyn = ms_start + pos * ms_per_sa;
390+ int dyn = 64;//m_dynamics[track].get_value( gtime_dyn );
391+ float amp = (float)dyn * k_inv64;
392+ float v = ((short)(wavbuf[c] | wavbuf[c + 1] << 8)) * k_inv32768 * amp;
393+ left[pos] += v;
394+ right[pos] += v;
395+ c += 2;
396+ len -= 2;
397+ pos++;
398+ }
399+ }
400+ } else {
401+ while ( pos < sampleFrames ) {
402+ int len = dat.Read( wavbuf, 0, buflen );
403+ if ( len <= 0 ) {
404+ break;
405+ }
406+ int c = 0;
407+ while ( len > 0 && pos < sampleFrames ) {
408+ double gtime_dyn = ms_start + pos * ms_per_sa;
409+ int dyn = 64;//m_dynamics[track].get_value( gtime_dyn );
410+ float amp = (float)dyn * k_inv64;
411+ left[pos] += ((short)(wavbuf[c] | wavbuf[c + 1] << 8)) * k_inv32768 * amp;
412+ right[pos] += ((short)(wavbuf[c + 2] | wavbuf[c + 3] << 8)) * k_inv32768 * amp;
413+ c += 4;
414+ len -= 4;
415+ pos++;
416+ }
417+ }
418+ }
419+ }
420+ #endregion
421+ }
422+#if DEBUG
423+ Common.DebugWriteLine( "calling WaveIncoming..." );
424+#endif
425+ WaveIncoming.Invoke( left, right );
426+#if DEBUG
427+ Common.DebugWriteLine( "...done" );
428+#endif
429+ processed_sample = sample_end;
430+ }
431+ }
432+ } catch ( Exception ex ) {
433+#if DEBUG
434+ Common.DebugWriteLine( "RenderUtau.StartRendering; ex=" + ex );
435+#endif
436+ }
437+ }
438+
439+ /// <summary>
440+ /// ひたすらresamplerを走らせるスレッド用
441+ /// </summary>
442+ private static void ResamplerProc( object parameter ) {
443+ try {
444+ string[] args = (string[])parameter;
445+ string resampler = args[0];
446+ string temp_dir = args[1];
447+ bool invoke_with_wine = (args[2].ToLower() == "true");
448+ while ( true ) {
449+ if ( s_abort_required ) {
450+ return;
451+ }
452+ if ( s_index + 2 < s_resampler_queue.Count ) {
453+ s_index++;
454+ Phon p = s_resampler_queue[s_index];
455+ if ( p.ModeR ) {
456+ s_resampler_queue[s_index].ResamplFinished = true;
457+ continue;
458+ }
459+ Phon p_next = s_resampler_queue[s_index + 1];
460+ int velocity = 100;
461+ int moduration = p.Event.Moduration;
462+ string flags = p.Event.Flags + "L";
463+ int time_percent = 100;
464+ string lyric = p.Lyric;
465+ string filename = p.FileName;
466+ string note = p.Note;
467+ OtoArgs oa = p.Oto;
468+ string singer = p.SingerDir;
469+ // C4 100 L 0 550 0 0 100 100
470+ string arg = "\"" + Path.Combine( singer, lyric + ".wav" ) + "\" \"" + filename + "\" \"" + note + "\" " + time_percent + " " + flags + " " + oa.msOffset + " " + p.msDuration + " " + oa.msConsonant + " " + oa.msBlank + " " + velocity + " " + moduration;
471+ using ( Process process = new Process() ) {
472+ process.StartInfo.FileName = (invoke_with_wine ? "wine \"" : "\"") + resampler + "\"";
473+ process.StartInfo.Arguments = arg;
474+ process.StartInfo.WorkingDirectory = temp_dir;
475+ process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
476+ process.Start();
477+ process.WaitForExit();
478+ }
479+ s_resampler_queue[s_index].ResamplFinished = true;
480+ }
481+ Application.DoEvents();
482+ }
483+ } catch ( Exception ex ) {
484+#if DEBUG
485+ Common.DebugWriteLine( "RenderUtau.ResamplerProc; ex=" + ex );
486+#endif
487+ }
488+ }
489+
490+ private static void ProcessWavtool( Phon p, UstEnvelope env, OtoArgs oa_next, string filebase, string temp_dir, string wavtool, bool invoke_with_wine ) {
491+ OtoArgs oa = p.Oto;
492+ int mten = oa.msPreUtterance + oa_next.msOverlap - oa_next.msPreUtterance;
493+ string arg = filebase + " \"" + p.FileName + "\" 0 " + p.ClockLength + "@" + string.Format( "{0:f2}", p.Tempo ) + mten.ToString( "+#;-#;0" );
494+ if ( p.ModeR ) {
495+ arg += " 0 0";
496+ } else {
497+ arg += " " + env.p1 + " " + env.p2 + " " + env.p3 + " " + env.v1 + " " + env.v2 + " " + env.v3 + " " + env.v4;
498+ arg += " " + oa.msOverlap + " " + env.p4 + " " + env.p5 + " " + env.v5;
499+ }
500+
501+ using ( Process process = new Process() ) {
502+ process.StartInfo.FileName = (invoke_with_wine ? "wine \"" : "\"") + wavtool + "\"";
503+ process.StartInfo.Arguments = arg;
504+ process.StartInfo.WorkingDirectory = temp_dir;
505+ process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
506+ process.Start();
507+ process.WaitForExit();
508+ }
509+ }
510+
511+ private static string NoteStringFromNoteNumber( int note_number ) {
512+ int odd = note_number % 12;
513+ string head = (new string[] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" })[odd];
514+ return head + (note_number / 12 - 1);
515+ }
516+ }
517+
518+}
--- trunk/Cadencii/VSTiProxy.cs (revision 161)
+++ trunk/Cadencii/VSTiProxy.cs (revision 162)
@@ -38,9 +38,7 @@
3838 private const int _SAMPLE_RATE = 44100;
3939 private const int _BLOCK_SIZE = 44100;
4040
41- //private static string s_dll_path = "";
4241 public static string CurrentUser = "";
43- //private static bool s_loaded = false;
4442 private static WaveWriter s_wave;
4543 private static bool s_rendering = false;
4644 private static int s_trim_remain = 0;
@@ -49,7 +47,8 @@
4947 private static double s_amplify_right = 1.0;
5048 private static string s_working_renderer = "";
5149 private static List<VstiRenderer> m_vstidrv = new List<VstiRenderer>();
52- public static event Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWritten;
50+ private static bool s_direct_play;
51+ //public static event Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWritten;
5352
5453 private class StartRenderArg {
5554 public string renderer;
@@ -64,6 +63,17 @@
6463 public bool mode_infinite;
6564 }
6665
66+ private class StartUtauRenderArg {
67+ public VsqFile vsq;
68+ public int track;
69+ public UtauSingerConfigSys utau_singers;
70+ public string path_resampler;
71+ public string path_wavtool;
72+ public string path_temp;
73+ public bool invoke_with_wine;
74+ public int sample_rate;
75+ }
76+
6777 private class VstiRenderer {
6878 #if UNMANAGED_VSTIDRV
6979 public vstildr DllInstance = null;
@@ -73,7 +83,7 @@
7383 public bool Loaded = false;
7484 public string Path = "";
7585 public string Name = "";
76- public volatile Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWrittenEventHandler = null;
86+ //public volatile Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWrittenEventHandler = null;
7787 }
7888
7989 static VSTiProxy() {
@@ -85,6 +95,7 @@
8595 if ( Environment.OSVersion.Platform == PlatformID.Unix ) {
8696 return;
8797 }
98+ PlaySound.Init( _BLOCK_SIZE, _SAMPLE_RATE );
8899 #if !DEBUG
89100 try {
90101 #endif
@@ -130,7 +141,7 @@
130141 vocalo2_dll_path = "";
131142 }
132143 string vocalo1_dll_path = VocaloSysUtil.getDllPathVsti1();
133- string utauvsti_dll_path = AppManager.EditorConfig.PathUtauVSTi;
144+ //string utauvsti_dll_path = AppManager.EditorConfig.PathUtauVSTi;
134145 if ( vocalo2_dll_path != "" && File.Exists( vocalo2_dll_path ) ) {
135146 VstiRenderer vr = new VstiRenderer();
136147 vr.Path = vocalo2_dll_path;
@@ -147,7 +158,7 @@
147158 vr.Name = RENDERER_DSB2;
148159 m_vstidrv.Add( vr );
149160 }
150- if ( utauvsti_dll_path != "" && File.Exists( utauvsti_dll_path ) ) {
161+ /*if ( utauvsti_dll_path != "" && File.Exists( utauvsti_dll_path ) ) {
151162 VstiRenderer vr = new VstiRenderer();
152163 vr.Path = utauvsti_dll_path;
153164 vr.Loaded = false;
@@ -154,7 +165,7 @@
154165 vr.DllInstance = (vstildr)asm.CreateInstance( driver_fullname );
155166 vr.Name = RENDERER_UTU0;
156167 m_vstidrv.Add( vr );
157- }
168+ }*/
158169 #else
159170 string vocalo2_dll_path = VocaloSysUtil.getDllPathVsti2();
160171 string vocalo1_dll_path = VocaloSysUtil.getDllPathVsti1();
@@ -201,14 +212,11 @@
201212 string dll_path = m_vstidrv[i].Path;
202213 bool loaded = false;
203214 try {
204-#if TEST
205- //s_dll_path = @"C:\Program Files\Steinberg\VSTplugins\utauvsti\utauvsti.dll";
206-#endif
207215 char[] str = dll_path.ToCharArray();
208216 if ( dll_path != "" ) {
209217 loaded = m_vstidrv[i].DllInstance.Init( str, _BLOCK_SIZE, _SAMPLE_RATE );
210- m_vstidrv[i].FirstBufferWrittenEventHandler = new FirstBufferWrittenCallback( HandleFirstBufferWrittenEvent );
211- m_vstidrv[i].DllInstance.SetFirstBufferWrittenCallback( m_vstidrv[i].FirstBufferWrittenEventHandler );
218+ //m_vstidrv[i].FirstBufferWrittenEventHandler = new FirstBufferWrittenCallback( HandleFirstBufferWrittenEvent );
219+ //m_vstidrv[i].DllInstance.SetFirstBufferWrittenCallback( m_vstidrv[i].FirstBufferWrittenEventHandler );
212220 } else {
213221 loaded = false;
214222 }
@@ -235,6 +243,12 @@
235243 return true;
236244 }
237245 }
246+ if ( renderer.StartsWith( RENDERER_UTU0 ) ) {
247+ if ( AppManager.PathResampler != "" && File.Exists( AppManager.PathResampler ) &&
248+ AppManager.PathWavtool != "" && File.Exists( AppManager.PathWavtool ) ) {
249+ return true;
250+ }
251+ }
238252 return false;
239253 }
240254
@@ -242,9 +256,9 @@
242256 #if TEST
243257 bocoree.debug.push_log( "VSTiProxy.HandleFirstBufferWrittenEvent" );
244258 #endif
245- if ( FirstBufferWritten != null ) {
259+ /*if ( FirstBufferWritten != null ) {
246260 FirstBufferWritten();
247- }
261+ }*/
248262 }
249263
250264 public static int SampleRate {
@@ -287,7 +301,8 @@
287301 bool direct_play,
288302 string[] files,
289303 double wave_read_offset_seconds,
290- bool mode_infinite
304+ bool mode_infinite,
305+ string temp_dir
291306 ) {
292307 #if TEST
293308 Common.DebugWriteLine( "VSTiProxy+Render" );
@@ -294,6 +309,7 @@
294309 Common.DebugWriteLine( " start_sec,end_sec=" + start_sec + "," + end_sec );
295310 #endif
296311 s_working_renderer = VSTiProxy.RENDERER_DSB3;
312+ s_direct_play = direct_play;
297313 string version = vsq.Track[track].getCommon().Version;
298314 if ( version.StartsWith( VSTiProxy.RENDERER_DSB2 ) ) {
299315 s_working_renderer = VSTiProxy.RENDERER_DSB2;
@@ -332,34 +348,64 @@
332348 long total_samples = (long)((end_sec - start_sec) * _SAMPLE_RATE);
333349 int trim_msec = (int)(trim_sec * 1000.0);
334350 if ( direct_play ) {
335- StartRenderArg sra = new StartRenderArg();
336- sra.renderer = s_working_renderer;
337- sra.nrpn = nrpn_data;
338- sra.tempo = split.getTempoList().ToArray();
339- sra.amplify_left = amplify_left;
340- sra.amplify_right = amplify_right;
341- sra.trim_msec = trim_msec;
342- sra.total_samples = total_samples;
343- sra.files = files;
344- sra.wave_read_offset_seconds = wave_read_offset_seconds;
345- sra.mode_infinite = mode_infinite;
351+ if ( s_working_renderer == VSTiProxy.RENDERER_UTU0 ) {
352+ StartUtauRenderArg sura = new StartUtauRenderArg();
353+ sura.vsq = split;
354+ sura.track = track;
355+ sura.utau_singers = AppManager.UtauSingers;
356+ sura.path_resampler = AppManager.PathResampler;
357+ sura.path_wavtool = AppManager.PathWavtool;
358+ sura.path_temp = temp_dir;
359+ sura.invoke_with_wine = AppManager.EditorConfig.InvokeUtauCoreWithWine;
360+ sura.sample_rate = _SAMPLE_RATE;
346361
347- Thread thread = new Thread( new ParameterizedThreadStart( RenderWithDirectPlay ) );
348- thread.Priority = ThreadPriority.BelowNormal;
349- thread.Start( sra );
362+ Thread thread = new Thread( new ParameterizedThreadStart( RenderUtauWithDirectPlay ) );
363+ thread.Priority = ThreadPriority.BelowNormal;
364+ thread.Start( sura );
365+ } else {
366+ StartRenderArg sra = new StartRenderArg();
367+ sra.renderer = s_working_renderer;
368+ sra.nrpn = nrpn_data;
369+ sra.tempo = split.getTempoList().ToArray();
370+ sra.amplify_left = amplify_left;
371+ sra.amplify_right = amplify_right;
372+ sra.trim_msec = trim_msec;
373+ sra.total_samples = total_samples;
374+ sra.files = files;
375+ sra.wave_read_offset_seconds = wave_read_offset_seconds;
376+ sra.mode_infinite = mode_infinite;
377+
378+ Thread thread = new Thread( new ParameterizedThreadStart( RenderWithDirectPlay ) );
379+ thread.Priority = ThreadPriority.BelowNormal;
380+ thread.Start( sra );
381+ }
350382 } else {
351- RenderCor( s_working_renderer,
352- nrpn_data,
353- split.getTempoList().ToArray(),
354- file,
355- amplify_left,
356- amplify_right,
357- direct_play,
358- trim_msec,
359- total_samples,
360- files,
361- wave_read_offset_seconds,
362- mode_infinite );
383+ if ( s_working_renderer == VSTiProxy.RENDERER_UTU0 ) {
384+ RenderUtau.WaveIncoming += vstidrv_WaveIncoming;
385+ s_trim_remain = 0;
386+ RenderUtau.StartRendering( split,
387+ track,
388+ AppManager.UtauSingers,
389+ AppManager.PathResampler,
390+ AppManager.PathWavtool,
391+ temp_dir,
392+ AppManager.EditorConfig.InvokeUtauCoreWithWine,
393+ _SAMPLE_RATE );
394+ RenderUtau.WaveIncoming -= vstidrv_WaveIncoming;
395+ } else {
396+ RenderCor( s_working_renderer,
397+ nrpn_data,
398+ split.getTempoList().ToArray(),
399+ file,
400+ amplify_left,
401+ amplify_right,
402+ direct_play,
403+ trim_msec,
404+ total_samples,
405+ files,
406+ wave_read_offset_seconds,
407+ mode_infinite );
408+ }
363409 }
364410 }
365411
@@ -379,10 +425,26 @@
379425 sra.mode_infinite );
380426 }
381427
428+ private static void RenderUtauWithDirectPlay( object argument ) {
429+ StartUtauRenderArg sura = (StartUtauRenderArg)argument;
430+ RenderUtau.WaveIncoming += vstidrv_WaveIncoming;
431+ s_trim_remain = 0;
432+ RenderUtau.StartRendering( sura.vsq,
433+ sura.track,
434+ sura.utau_singers,
435+ sura.path_resampler,
436+ sura.path_wavtool,
437+ sura.path_temp,
438+ sura.invoke_with_wine,
439+ sura.sample_rate );
440+ RenderUtau.WaveIncoming -= vstidrv_WaveIncoming;
441+ }
442+
382443 public static void WaveOutReset() {
383444 for ( int i = 0; i < m_vstidrv.Count; i++ ) {
384445 if ( m_vstidrv[i].Loaded ) {
385- m_vstidrv[i].DllInstance.WaveOutReset();
446+ //m_vstidrv[i].DllInstance.WaveOutReset();
447+ PlaySound.Reset();
386448 }
387449 }
388450 }
@@ -405,6 +467,7 @@
405467 Console.WriteLine( "VSTiProxy.RenderToWave( NRPN[], TempoTableEntry[], int, string )" );
406468 bocoree.debug.push_log( "VSTiPRoxy+RenderToWave(NrpnData[], TempoTableEntry[], int, string)" );
407469 #endif
470+ s_direct_play = direct_play;
408471 int index_driver = -1;
409472 for ( int i = 0; i < m_vstidrv.Count; i++ ) {
410473 if ( m_vstidrv[i].Name == renderer ) {
@@ -445,10 +508,7 @@
445508 masterEventsSrc[count + 1] = b1;
446509 masterEventsSrc[count + 2] = b2;
447510 }
448- //fixed ( byte* masterEvents = &masterEventsSrc[0] )
449- //fixed ( int* masterClocks = &masterClocksSrc[0] ) {
450- m_vstidrv[index_driver].DllInstance.SendEvent( masterEventsSrc, masterClocksSrc, VSTiProxyTrackType.TempoTrack );
451- //}
511+ m_vstidrv[index_driver].DllInstance.SendEvent( masterEventsSrc, masterClocksSrc, VSTiProxyTrackType.TempoTrack );
452512
453513 int numEvents = nrpn.Length;
454514 byte[] bodyEventsSrc = new byte[numEvents * 3];
@@ -478,14 +538,10 @@
478538 #if DEBUG
479539 Common.DebugWriteLine( " s_trim_remain=" + s_trim_remain );
480540 #endif
481- //fixed ( byte* bodyEvents = &bodyEventsSrc[0] )
482- //fixed ( int* bodyClocks = &bodyClocksSrc[0] ) {
483- m_vstidrv[index_driver].DllInstance.SendEvent( bodyEventsSrc, bodyClocksSrc, VSTiProxyTrackType.MainTrack );
484- //}
541+ m_vstidrv[index_driver].DllInstance.SendEvent( bodyEventsSrc, bodyClocksSrc, VSTiProxyTrackType.MainTrack );
485542
486543 s_rendering = true;
487544 if ( file != null ) {
488- //s_wave = new WaveWriter( file, WaveChannel.Stereo, 16, _SAMPLE_RATE );
489545 s_wave = file;
490546 if ( s_trim_remain < 0 ) {
491547 double[] d = new double[-s_trim_remain];
@@ -503,27 +559,22 @@
503559
504560 s_amplify_left = amplify_left;
505561 s_amplify_right = amplify_right;
506- if ( file != null ) {
562+ //if ( file != null ) {
507563 m_vstidrv[index_driver].DllInstance.WaveIncoming += vstidrv_WaveIncoming;
508- }
564+ //}
509565 m_vstidrv[index_driver].DllInstance.RenderingFinished += vstidrv_RenderingFinished;
510- m_vstidrv[index_driver].DllInstance.StartRendering( total_samples,
511- 1.0,
512- 1.0,
513- trim_remain,
514- (file != null),
515- direct_play,
516- files,
517- wave_read_offset_seconds,
518- mode_infinite );
566+#if DEBUG
567+ m_vstidrv[index_driver].DllInstance.StartRendering( total_samples, 1.0, 1.0 );
568+#else
569+ m_vstidrv[index_driver].DllInstance.StartRendering( total_samples, 1.0, 1.0 );
570+#endif
519571 while ( s_rendering ) {
520572 Application.DoEvents();
521573 }
522574 s_rendering = false;
523- if ( file != null ) {
575+ //if ( file != null ) {
524576 m_vstidrv[index_driver].DllInstance.WaveIncoming -= vstidrv_WaveIncoming;
525- //s_wave.Close();
526- }
577+ //}
527578 m_vstidrv[index_driver].DllInstance.RenderingFinished -= vstidrv_RenderingFinished;
528579 s_wave = null;
529580 }
@@ -532,22 +583,15 @@
532583 s_rendering = false;
533584 }
534585
535- static void vstidrv_WaveIncoming( double[] L, double[] R ) {
586+ static unsafe void vstidrv_WaveIncoming( double[] L, double[] R ) {
536587 #if TEST
537588 bocoree.debug.push_log( "VSTiProxy.vstidrv_WaveIncoming" );
538589 bocoree.debug.push_log( " requiring lock of s_locker..." );
539590 #endif
540591 lock ( s_locker ) {
541-#if TEST
542- bocoree.debug.push_log( " ...done" );
543- bocoree.debug.push_log( " s_trim_remain=" + s_trim_remain );
544-#endif
545592 if ( s_trim_remain > 0 ) {
546593 if ( s_trim_remain >= L.Length ) {
547594 s_trim_remain -= L.Length;
548-#if TEST
549- //bocoree.debug.push_log( " ...lock released" );
550-#endif
551595 return;
552596 }
553597 int actual_append = L.Length - s_trim_remain;
@@ -557,10 +601,15 @@
557601 dL[i] = L[i + s_trim_remain] * s_amplify_left;
558602 dR[i] = R[i + s_trim_remain] * s_amplify_right;
559603 }
560-#if TEST
561- bocoree.debug.push_log( " calling s_wave.Append (1)" );
562-#endif
563- s_wave.Append( dL, dR );
604+ if ( s_wave != null ){
605+ s_wave.Append( dL, dR );
606+ }
607+ if ( s_direct_play ) {
608+ fixed ( double* pl = &dL[0] )
609+ fixed ( double* pr = &dR[0] ) {
610+ PlaySound.Append( pl, pr, actual_append );
611+ }
612+ }
564613 dL = null;
565614 dR = null;
566615 s_trim_remain = 0;
@@ -571,14 +620,19 @@
571620 for ( int i = 0; i < R.Length; i++ ) {
572621 R[i] = R[i] * s_amplify_right;
573622 }
574-#if TEST
575- bocoree.debug.push_log( " calling s_wave.Append (2)" );
576-#endif
577- s_wave.Append( L, R );
623+ if ( s_wave != null ) {
624+ s_wave.Append( L, R );
625+ }
626+ if ( s_direct_play ) {
627+ fixed ( double* pl = &L[0] )
628+ fixed ( double* pr = &R[0] ) {
629+ PlaySound.Append( pl, pr, L.Length );
630+ }
631+ }
578632 }
579633 }
580-#if TEST
581- bocoree.debug.push_log( " ...lock released" );
634+#if DEBUG
635+ bocoree.debug.push_log( "...done" );
582636 #endif
583637 }
584638
@@ -595,9 +649,13 @@
595649 if ( s_rendering ) {
596650 s_rendering = false;
597651 }
598- for ( int i = 0; i < m_vstidrv.Count; i++ ) {
599- if ( m_vstidrv[i].Loaded ) {
600- m_vstidrv[i].DllInstance.AbortRendering();
652+ if ( s_working_renderer == VSTiProxy.RENDERER_UTU0 ) {
653+ RenderUtau.AbortRendering();
654+ } else {
655+ for ( int i = 0; i < m_vstidrv.Count; i++ ) {
656+ if ( m_vstidrv[i].Loaded ) {
657+ m_vstidrv[i].DllInstance.AbortRendering();
658+ }
601659 }
602660 }
603661 }
@@ -615,12 +673,11 @@
615673 }
616674
617675 public static float GetPlayTime() {
618- for ( int i = 0; i < m_vstidrv.Count; i++ ) {
619- if ( m_vstidrv[i].Name == s_working_renderer ) {
620- return m_vstidrv[i].DllInstance.GetPlayTime();
621- }
622- }
623- return 0.0f;
676+ double pos = PlaySound.GetPosition();
677+#if DEBUG
678+ Common.DebugWriteLine( "VSTiProxy.GetPlayTime; pos=" + pos );
679+#endif
680+ return (float)pos;
624681 }
625682
626683 #if OBSOLUTE
--- trunk/Cadencii/FormMainUtil.cs (revision 161)
+++ trunk/Cadencii/FormMainUtil.cs (revision 162)
@@ -750,7 +750,6 @@
750750 #endif
751751 }
752752 if ( si.EditVsqDelegate != null ) {
753- m_manager.BgmPlayer.UnLoad();
754753 VsqFileEx old = (VsqFileEx)m_manager.VsqFile.Clone();
755754 if ( m_manager.InvokeScript( si ) ) {
756755 Edited = true;
--- trunk/Cadencii/FormMain.Designer.cs (revision 161)
+++ trunk/Cadencii/FormMain.Designer.cs (revision 162)
@@ -46,6 +46,7 @@
4646 this.menuFileSaveNamed = new System.Windows.Forms.ToolStripMenuItem();
4747 this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripSeparator();
4848 this.menuFileImport = new System.Windows.Forms.ToolStripMenuItem();
49+ this.menuFileImportVsq = new System.Windows.Forms.ToolStripMenuItem();
4950 this.menuFileImportUst = new System.Windows.Forms.ToolStripMenuItem();
5051 this.menuFileImportMidi = new System.Windows.Forms.ToolStripMenuItem();
5152 this.menuFileExport = new System.Windows.Forms.ToolStripMenuItem();
@@ -265,6 +266,7 @@
265266 this.vScroll = new Boare.Lib.AppUtil.BVScrollBar();
266267 this.hScroll = new Boare.Lib.AppUtil.BHScrollBar();
267268 this.picturePositionIndicator = new System.Windows.Forms.PictureBox();
269+ this.pictPianoRoll = new Boare.Cadencii.BPictureBox();
268270 this.pictureBox3 = new System.Windows.Forms.PictureBox();
269271 this.pictureBox2 = new System.Windows.Forms.PictureBox();
270272 this.toolStripTool = new System.Windows.Forms.ToolStrip();
@@ -294,6 +296,7 @@
294296 this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
295297 this.stripDDBtnSpeed = new System.Windows.Forms.ToolStripDropDownButton();
296298 this.panel2 = new System.Windows.Forms.Panel();
299+ this.waveView = new Boare.Cadencii.WaveView();
297300 this.splitContainer2 = new Boare.Lib.AppUtil.BSplitContainer();
298301 this.splitContainer1 = new Boare.Lib.AppUtil.BSplitContainer();
299302 this.toolStripPosition = new System.Windows.Forms.ToolStrip();
@@ -348,9 +351,6 @@
348351 this.openUstDialog = new System.Windows.Forms.OpenFileDialog();
349352 this.openMidiDialog = new System.Windows.Forms.OpenFileDialog();
350353 this.saveMidiDialog = new System.Windows.Forms.SaveFileDialog();
351- this.waveView = new Boare.Cadencii.WaveView();
352- this.pictPianoRoll = new Boare.Cadencii.BPictureBox();
353- this.menuFileImportVsq = new System.Windows.Forms.ToolStripMenuItem();
354354 this.menuStripMain.SuspendLayout();
355355 this.cMenuPiano.SuspendLayout();
356356 this.cMenuTrackTab.SuspendLayout();
@@ -358,6 +358,7 @@
358358 ((System.ComponentModel.ISupportInitialize)(this.trackBar)).BeginInit();
359359 this.panel1.SuspendLayout();
360360 ((System.ComponentModel.ISupportInitialize)(this.picturePositionIndicator)).BeginInit();
361+ ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).BeginInit();
361362 ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
362363 ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
363364 this.toolStripTool.SuspendLayout();
@@ -370,7 +371,6 @@
370371 this.toolStripPosition.SuspendLayout();
371372 this.toolStripMeasure.SuspendLayout();
372373 this.toolStripFile.SuspendLayout();
373- ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).BeginInit();
374374 this.SuspendLayout();
375375 //
376376 // menuStripMain
@@ -416,7 +416,7 @@
416416 //
417417 this.menuFileNew.Name = "menuFileNew";
418418 this.menuFileNew.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
419- this.menuFileNew.Size = new System.Drawing.Size( 152, 22 );
419+ this.menuFileNew.Size = new System.Drawing.Size( 151, 22 );
420420 this.menuFileNew.Text = "New(N)";
421421 this.menuFileNew.Click += new System.EventHandler( this.commonFileNew_Click );
422422 //
@@ -424,7 +424,7 @@
424424 //
425425 this.menuFileOpen.Name = "menuFileOpen";
426426 this.menuFileOpen.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
427- this.menuFileOpen.Size = new System.Drawing.Size( 152, 22 );
427+ this.menuFileOpen.Size = new System.Drawing.Size( 151, 22 );
428428 this.menuFileOpen.Text = "Open(&O)";
429429 this.menuFileOpen.Click += new System.EventHandler( this.commonFileOpen_Click );
430430 //
@@ -432,7 +432,7 @@
432432 //
433433 this.menuFileSave.Name = "menuFileSave";
434434 this.menuFileSave.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)));
435- this.menuFileSave.Size = new System.Drawing.Size( 152, 22 );
435+ this.menuFileSave.Size = new System.Drawing.Size( 151, 22 );
436436 this.menuFileSave.Text = "Save(&S)";
437437 this.menuFileSave.Click += new System.EventHandler( this.commonFileSave_Click );
438438 //
@@ -439,7 +439,7 @@
439439 // menuFileSaveNamed
440440 //
441441 this.menuFileSaveNamed.Name = "menuFileSaveNamed";
442- this.menuFileSaveNamed.Size = new System.Drawing.Size( 152, 22 );
442+ this.menuFileSaveNamed.Size = new System.Drawing.Size( 151, 22 );
443443 this.menuFileSaveNamed.Text = "Save As(&A)";
444444 this.menuFileSaveNamed.Click += new System.EventHandler( this.menuFileSaveNamed_Click );
445445 //
@@ -446,7 +446,7 @@
446446 // toolStripMenuItem10
447447 //
448448 this.toolStripMenuItem10.Name = "toolStripMenuItem10";
449- this.toolStripMenuItem10.Size = new System.Drawing.Size( 149, 6 );
449+ this.toolStripMenuItem10.Size = new System.Drawing.Size( 148, 6 );
450450 //
451451 // menuFileImport
452452 //
@@ -455,9 +455,16 @@
455455 this.menuFileImportUst,
456456 this.menuFileImportMidi} );
457457 this.menuFileImport.Name = "menuFileImport";
458- this.menuFileImport.Size = new System.Drawing.Size( 152, 22 );
458+ this.menuFileImport.Size = new System.Drawing.Size( 151, 22 );
459459 this.menuFileImport.Text = "Import(&I)";
460460 //
461+ // menuFileImportVsq
462+ //
463+ this.menuFileImportVsq.Name = "menuFileImportVsq";
464+ this.menuFileImportVsq.Size = new System.Drawing.Size( 164, 22 );
465+ this.menuFileImportVsq.Text = "VSQ File";
466+ this.menuFileImportVsq.Click += new System.EventHandler( this.menuFileImportVsq_Click );
467+ //
461468 // menuFileImportUst
462469 //
463470 this.menuFileImportUst.Name = "menuFileImportUst";
@@ -478,7 +485,7 @@
478485 this.menuFileExportWave,
479486 this.menuFileExportMidi} );
480487 this.menuFileExport.Name = "menuFileExport";
481- this.menuFileExport.Size = new System.Drawing.Size( 152, 22 );
488+ this.menuFileExport.Size = new System.Drawing.Size( 151, 22 );
482489 this.menuFileExport.Text = "Export(&E)";
483490 this.menuFileExport.DropDownOpening += new System.EventHandler( this.menuFileExport_DropDownOpening );
484491 //
@@ -485,7 +492,7 @@
485492 // menuFileExportWave
486493 //
487494 this.menuFileExportWave.Name = "menuFileExportWave";
488- this.menuFileExportWave.Size = new System.Drawing.Size( 152, 22 );
495+ this.menuFileExportWave.Size = new System.Drawing.Size( 97, 22 );
489496 this.menuFileExportWave.Text = "Wave";
490497 this.menuFileExportWave.Click += new System.EventHandler( this.menuFileExportWave_Click );
491498 //
@@ -492,7 +499,7 @@
492499 // menuFileExportMidi
493500 //
494501 this.menuFileExportMidi.Name = "menuFileExportMidi";
495- this.menuFileExportMidi.Size = new System.Drawing.Size( 152, 22 );
502+ this.menuFileExportMidi.Size = new System.Drawing.Size( 97, 22 );
496503 this.menuFileExportMidi.Text = "MIDI";
497504 this.menuFileExportMidi.Click += new System.EventHandler( this.menuFileExportMidi_Click );
498505 //
@@ -499,24 +506,24 @@
499506 // toolStripMenuItem11
500507 //
501508 this.toolStripMenuItem11.Name = "toolStripMenuItem11";
502- this.toolStripMenuItem11.Size = new System.Drawing.Size( 149, 6 );
509+ this.toolStripMenuItem11.Size = new System.Drawing.Size( 148, 6 );
503510 //
504511 // menuFileRecent
505512 //
506513 this.menuFileRecent.Name = "menuFileRecent";
507- this.menuFileRecent.Size = new System.Drawing.Size( 152, 22 );
514+ this.menuFileRecent.Size = new System.Drawing.Size( 151, 22 );
508515 this.menuFileRecent.Text = "Recent Files(&R)";
509516 //
510517 // toolStripMenuItem12
511518 //
512519 this.toolStripMenuItem12.Name = "toolStripMenuItem12";
513- this.toolStripMenuItem12.Size = new System.Drawing.Size( 149, 6 );
520+ this.toolStripMenuItem12.Size = new System.Drawing.Size( 148, 6 );
514521 //
515522 // menuFileQuit
516523 //
517524 this.menuFileQuit.Name = "menuFileQuit";
518525 this.menuFileQuit.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Q)));
519- this.menuFileQuit.Size = new System.Drawing.Size( 152, 22 );
526+ this.menuFileQuit.Size = new System.Drawing.Size( 151, 22 );
520527 this.menuFileQuit.Text = "Quit(&Q)";
521528 this.menuFileQuit.Click += new System.EventHandler( this.menuFileQuit_Click );
522529 //
@@ -1261,6 +1268,7 @@
12611268 this.menuSettingBgm.Name = "menuSettingBgm";
12621269 this.menuSettingBgm.Size = new System.Drawing.Size( 200, 22 );
12631270 this.menuSettingBgm.Text = "BGM(&B)";
1271+ this.menuSettingBgm.Visible = false;
12641272 //
12651273 // menuSettingBgmSetSound
12661274 //
@@ -1397,7 +1405,7 @@
13971405 this.tToolStripMenuItem.Size = new System.Drawing.Size( 264, 22 );
13981406 this.tToolStripMenuItem.Text = "t";
13991407 //
1400- // saveVsqDialog
1408+ // saveXmlVsqDialog
14011409 //
14021410 this.saveXmlVsqDialog.Filter = "VSQ Format(*.vsq)|*.vsq|Original Format(*.evsq)|*.evsq|All files(*.*)|*.*";
14031411 //
@@ -1847,7 +1855,7 @@
18471855 this.cMenuPianoVibratoProperty.Text = "Note Vibrato Property";
18481856 this.cMenuPianoVibratoProperty.Click += new System.EventHandler( this.cMenuPianoVibratoProperty_Click );
18491857 //
1850- // openVsqDialog
1858+ // openXmlVsqDialog
18511859 //
18521860 this.openXmlVsqDialog.Filter = "VSQ Format(*.vsq)|*.vsq|Original Format(*.evsq)|*.evsq";
18531861 //
@@ -2227,6 +2235,28 @@
22272235 this.picturePositionIndicator.Paint += new System.Windows.Forms.PaintEventHandler( this.picturePositionIndicator_Paint );
22282236 this.picturePositionIndicator.MouseEnter += new System.EventHandler( this.picturePositionIndicator_MouseEnter );
22292237 //
2238+ // pictPianoRoll
2239+ //
2240+ this.pictPianoRoll.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
2241+ | System.Windows.Forms.AnchorStyles.Left)
2242+ | System.Windows.Forms.AnchorStyles.Right)));
2243+ this.pictPianoRoll.BackColor = System.Drawing.Color.FromArgb( ((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))) );
2244+ this.pictPianoRoll.Location = new System.Drawing.Point( 0, 48 );
2245+ this.pictPianoRoll.Margin = new System.Windows.Forms.Padding( 0 );
2246+ this.pictPianoRoll.Name = "pictPianoRoll";
2247+ this.pictPianoRoll.Size = new System.Drawing.Size( 405, 218 );
2248+ this.pictPianoRoll.TabIndex = 12;
2249+ this.pictPianoRoll.TabStop = false;
2250+ this.pictPianoRoll.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler( this.pictPianoRoll_PreviewKeyDown );
2251+ this.pictPianoRoll.BKeyUp += new System.Windows.Forms.KeyEventHandler( this.anonymousCaptureSpaceKeyUp );
2252+ this.pictPianoRoll.MouseMove += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseMove );
2253+ this.pictPianoRoll.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseDoubleClick );
2254+ this.pictPianoRoll.MouseClick += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseClick );
2255+ this.pictPianoRoll.MouseDown += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseDown );
2256+ this.pictPianoRoll.Paint += new System.Windows.Forms.PaintEventHandler( this.pictPianoRoll_Paint );
2257+ this.pictPianoRoll.MouseUp += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseUp );
2258+ this.pictPianoRoll.BKeyDown += new System.Windows.Forms.KeyEventHandler( this.anonymousCaptureSpaceKeyDown );
2259+ //
22302260 // pictureBox3
22312261 //
22322262 this.pictureBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@@ -2510,6 +2540,18 @@
25102540 this.panel2.Size = new System.Drawing.Size( 421, 59 );
25112541 this.panel2.TabIndex = 19;
25122542 //
2543+ // waveView
2544+ //
2545+ this.waveView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
2546+ | System.Windows.Forms.AnchorStyles.Left)
2547+ | System.Windows.Forms.AnchorStyles.Right)));
2548+ this.waveView.BackColor = System.Drawing.Color.FromArgb( ((int)(((byte)(212)))), ((int)(((byte)(212)))), ((int)(((byte)(212)))) );
2549+ this.waveView.Location = new System.Drawing.Point( 66, 0 );
2550+ this.waveView.Margin = new System.Windows.Forms.Padding( 0 );
2551+ this.waveView.Name = "waveView";
2552+ this.waveView.Size = new System.Drawing.Size( 355, 59 );
2553+ this.waveView.TabIndex = 17;
2554+ //
25132555 // splitContainer2
25142556 //
25152557 this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
@@ -3049,47 +3091,6 @@
30493091 //
30503092 this.openUstDialog.Filter = "UTAU Project File(*.ust)|*.ust|All Files(*.*)|*.*";
30513093 //
3052- // waveView
3053- //
3054- this.waveView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
3055- | System.Windows.Forms.AnchorStyles.Left)
3056- | System.Windows.Forms.AnchorStyles.Right)));
3057- this.waveView.BackColor = System.Drawing.Color.FromArgb( ((int)(((byte)(212)))), ((int)(((byte)(212)))), ((int)(((byte)(212)))) );
3058- this.waveView.Location = new System.Drawing.Point( 66, 0 );
3059- this.waveView.Margin = new System.Windows.Forms.Padding( 0 );
3060- this.waveView.Name = "waveView";
3061- this.waveView.Size = new System.Drawing.Size( 355, 59 );
3062- this.waveView.TabIndex = 17;
3063- //
3064- // pictPianoRoll
3065- //
3066- this.pictPianoRoll.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
3067- | System.Windows.Forms.AnchorStyles.Left)
3068- | System.Windows.Forms.AnchorStyles.Right)));
3069- this.pictPianoRoll.BackColor = System.Drawing.Color.FromArgb( ((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))) );
3070- this.pictPianoRoll.Location = new System.Drawing.Point( 0, 48 );
3071- this.pictPianoRoll.Margin = new System.Windows.Forms.Padding( 0 );
3072- this.pictPianoRoll.Name = "pictPianoRoll";
3073- this.pictPianoRoll.Size = new System.Drawing.Size( 405, 218 );
3074- this.pictPianoRoll.TabIndex = 12;
3075- this.pictPianoRoll.TabStop = false;
3076- this.pictPianoRoll.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler( this.pictPianoRoll_PreviewKeyDown );
3077- this.pictPianoRoll.BKeyUp += new System.Windows.Forms.KeyEventHandler( this.anonymousCaptureSpaceKeyUp );
3078- this.pictPianoRoll.MouseMove += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseMove );
3079- this.pictPianoRoll.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseDoubleClick );
3080- this.pictPianoRoll.MouseClick += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseClick );
3081- this.pictPianoRoll.MouseDown += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseDown );
3082- this.pictPianoRoll.Paint += new System.Windows.Forms.PaintEventHandler( this.pictPianoRoll_Paint );
3083- this.pictPianoRoll.MouseUp += new System.Windows.Forms.MouseEventHandler( this.pictPianoRoll_MouseUp );
3084- this.pictPianoRoll.BKeyDown += new System.Windows.Forms.KeyEventHandler( this.anonymousCaptureSpaceKeyDown );
3085- //
3086- // menuFileImportVsq
3087- //
3088- this.menuFileImportVsq.Name = "menuFileImportVsq";
3089- this.menuFileImportVsq.Size = new System.Drawing.Size( 164, 22 );
3090- this.menuFileImportVsq.Text = "VSQ File";
3091- this.menuFileImportVsq.Click += new System.EventHandler( this.menuFileImportVsq_Click );
3092- //
30933094 // FormMain
30943095 //
30953096 this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 12F );
@@ -3117,6 +3118,7 @@
31173118 ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit();
31183119 this.panel1.ResumeLayout( false );
31193120 ((System.ComponentModel.ISupportInitialize)(this.picturePositionIndicator)).EndInit();
3121+ ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).EndInit();
31203122 ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
31213123 ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
31223124 this.toolStripTool.ResumeLayout( false );
@@ -3137,7 +3139,6 @@
31373139 this.toolStripMeasure.PerformLayout();
31383140 this.toolStripFile.ResumeLayout( false );
31393141 this.toolStripFile.PerformLayout();
3140- ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).EndInit();
31413142 this.ResumeLayout( false );
31423143 this.PerformLayout();
31433144
--- trunk/Cadencii/FormMain.cs (revision 161)
+++ trunk/Cadencii/FormMain.cs (revision 162)
@@ -855,11 +855,10 @@
855855 timer.Enabled = false;
856856 VSTiProxy.AbortRendering();
857857 VSTiProxy.WaveOutReset();
858- m_manager.BgmPlayer.Stop();
859858 for ( int i = 0; i < m_draw_start_index.Length; i++ ) {
860859 m_draw_start_index[i] = 0;
861860 }
862- VSTiProxy.FirstBufferWritten -= vstidrv_FirstBufferWritten;
861+ //VSTiProxy.FirstBufferWritten -= vstidrv_FirstBufferWritten;
863862 m_manager.FirstBufferWritten = false;
864863 if ( m_midi_in != null ) {
865864 m_midi_in.Stop();
@@ -1023,7 +1022,7 @@
10231022 Common.DebugWriteLine( "m_preview_ending_time=" + m_preview_ending_time );
10241023 #endif
10251024
1026- VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten;
1025+ //VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten;
10271026
10281027 VSTiProxy.Render( m_manager.VsqFile,
10291028 selected,
@@ -1036,7 +1035,8 @@
10361035 true,
10371036 sounds.ToArray(),
10381037 m_direct_play_shift,
1039- (m_manager.EditMode == EditMode.Realtime) );
1038+ (m_manager.EditMode == EditMode.Realtime),
1039+ m_manager.TempWaveDir );
10401040
10411041 for ( int i = 0; i < m_draw_start_index.Length; i++ ) {
10421042 m_draw_start_index[i] = 0;
@@ -1044,7 +1044,7 @@
10441044 int clock_now = m_manager.CurrentClock;
10451045 double sec_now = m_manager.VsqFile.getSecFromClock( clock_now );
10461046 } else {
1047- VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten;
1047+ //VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten;
10481048 VSTiProxy.Render( new VsqFile( 0, m_manager.VsqFile.getPreMeasure(), 4, 4, 500000 ),
10491049 1,
10501050 null,
@@ -1056,7 +1056,8 @@
10561056 true,
10571057 sounds.ToArray(),
10581058 m_direct_play_shift,
1059- (m_manager.EditMode == EditMode.Realtime) );
1059+ (m_manager.EditMode == EditMode.Realtime),
1060+ m_manager.TempWaveDir );
10601061 }
10611062 }
10621063
@@ -1068,6 +1069,7 @@
10681069 } else {
10691070 m_manager.RendererAvailable = VSTiProxy.IsRendererAvailable( renderer );
10701071 }
1072+ m_manager.FirstBufferWritten = true;
10711073 m_last_ignitted = DateTime.Now;
10721074 m_manager.PreviewStartedTime = m_last_ignitted;
10731075 #if DEBUG
@@ -1085,10 +1087,6 @@
10851087 m_manager.FirstBufferWritten = true;
10861088 m_last_regulated = DateTime.Now;
10871089 int selected = m_manager.Selected;
1088- if ( !menuSettingBgmMute.Checked && m_manager.BgmPlayer.SoundLocation != "" ) {
1089- m_manager.BgmPlayer.Speed = m_manager.Speed;
1090- m_manager.BgmPlayer.PlayFrom( m_direct_play_shift );
1091- }
10921090 }
10931091
10941092 private void m_manager_SelectedToolChanged( object sender, EventArgs e ) {
@@ -3841,7 +3839,7 @@
38413839 using ( OpenFileDialog ofd = new OpenFileDialog() ) {
38423840 ofd.Filter = _( "MP3 File(*.mp3)|*.mp3" ) + "|" + _( "Wave File(*.wav)|*.wav" ) + "|" + _( "All Files(*.*)|*.*" );
38433841 if ( ofd.ShowDialog() == DialogResult.OK ) {
3844- m_manager.BgmPlayer.Load( ofd.FileName );
3842+ //m_manager.BgmPlayer.Load( ofd.FileName );
38453843 }
38463844 }
38473845 }
--- trunk/Cadencii/EditorConfig.cs (revision 161)
+++ trunk/Cadencii/EditorConfig.cs (revision 162)
@@ -209,6 +209,8 @@
209209 public RgbColor PianorollColorUtauBeat = new RgbColor( 128, 128, 255 );
210210 [XmlItemDescription( "Show actual pitch line or not" )]
211211 public bool ViewAtcualPitch = false;
212+ [XmlItemDescription( "Invoke resampler with Wine" )]
213+ public bool InvokeUtauCoreWithWine = false;
212214
213215 /// <summary>
214216 /// PositionQuantize, PositionQuantizeTriplet, LengthQuantize, LengthQuantizeTripletの描くプロパティのいずれかが
--- trunk/Cadencii/EditorManager.cs (revision 161)
+++ trunk/Cadencii/EditorManager.cs (revision 162)
@@ -84,10 +84,6 @@
8484 /// </summary>
8585 private PlayPositionSpecifier m_current_play_position;
8686 /// <summary>
87- /// BGMプレイヤ
88- /// </summary>
89- private MediaPlayer m_bgm_player = new MediaPlayer();
90- /// <summary>
9187 /// プレビュー再生のスピード
9288 /// </summary>
9389 private float m_speed = 1.0f;
@@ -180,7 +176,7 @@
180176 #if DEBUG
181177 Common.DebugWriteLine( "EditorManager..ctor; log=" + log );
182178 #endif
183- bocoree.debug.force_logfile_path( log );
179+ //bocoree.debug.force_logfile_path( log );
184180 }
185181 #endif
186182 /// <summary>
@@ -320,15 +316,6 @@
320316 }
321317 }
322318
323- public MediaPlayer BgmPlayer {
324- get {
325- if ( m_bgm_player == null ) {
326- m_bgm_player = new MediaPlayer();
327- }
328- return m_bgm_player;
329- }
330- }
331-
332319 public string TempWaveDir {
333320 get {
334321 string temp = Path.Combine( AppManager.ApplicationDataPath, _TEMPDIR_NAME );
--- trunk/Cadencii/FormSynthesize.cs (revision 161)
+++ trunk/Cadencii/FormSynthesize.cs (revision 162)
@@ -142,7 +142,8 @@
142142 false,
143143 new string[] { },
144144 0.0,
145- false );
145+ false,
146+ m_manager.TempWaveDir );
146147 }
147148 } else {
148149 for ( int i = 0; i < m_tracks.Length; i++ ) {
@@ -174,7 +175,8 @@
174175 false,
175176 new string[] { },
176177 0.0,
177- false );
178+ false,
179+ m_manager.TempWaveDir );
178180 }
179181 }
180182 }
--- trunk/Boare.Lib.Vsq/VsqFile.cs (revision 161)
+++ trunk/Boare.Lib.Vsq/VsqFile.cs (revision 162)
@@ -2200,11 +2200,8 @@
22002200 if ( version.StartsWith( "DSB2" ) ) {
22012201 list.AddRange( generateFx2DepthNRPN( vsq, track, msPreSend ) );
22022202 }
2203- VsqBPList dyn = vsq.Track[track].getCurve( "dyn" );
2204- if ( dyn.getCount() > 0 ) {
2205- list.AddRange( generateExpressionNRPN( vsq, track, msPreSend ) );
2206- }
2207- int ms_presend_for_pitch = msPreSend;
2203+
2204+ int ms_presend = msPreSend;
22082205 if ( version.StartsWith( "UTU0" ) ) {
22092206 double sec_maxlen = 0.0;
22102207 for ( Iterator itr = vsq.Track[track].getNoteEventIterator(); itr.hasNext(); ) {
@@ -2212,15 +2209,41 @@
22122209 double len = vsq.getSecFromClock( ve.Clock + ve.ID.Length ) - vsq.getSecFromClock( ve.Clock );
22132210 sec_maxlen = Math.Max( sec_maxlen, len );
22142211 }
2215- if ( sec_maxlen * 1000.0 > msPreSend ) {
2216- ms_presend_for_pitch = (int)(sec_maxlen * 1000.0);
2212+ ms_presend += (int)(sec_maxlen * 1000.0);
2213+ }
2214+ VsqBPList dyn = vsq.Track[track].getCurve( "dyn" );
2215+ if ( dyn.getCount() > 0 ) {
2216+ List<VsqNrpn> listdyn = new List<VsqNrpn>( generateExpressionNRPN( vsq, track, ms_presend ) );
2217+ int index = 0;
2218+ while ( index < listdyn.Count ) {
2219+ if ( listdyn[index].Nrpn == NRPN.CC_E_EXPRESSION && listdyn[index].Clock < 0 ) {
2220+ listdyn.RemoveAt( index );
2221+ continue;
2222+ } else if ( listdyn[index].Nrpn == NRPN.CC_E_VESION_AND_DEVICE && listdyn[index].Clock < 0 ) {
2223+ listdyn[index].Clock = 0;
2224+ } else if ( listdyn[index].Nrpn == NRPN.CC_E_DELAY && listdyn[index].Clock < 0 ) {
2225+ listdyn[index].Clock = 0;
2226+ }
2227+ index++;
22172228 }
2229+ if ( listdyn.Count > 0 ) {
2230+ list.AddRange( listdyn );
2231+ }
22182232 }
22192233 VsqBPList pbs = vsq.Track[track].getCurve( "pbs" );
22202234 if ( pbs.getCount() > 0 ) {
2221- List<VsqNrpn> listpbs = new List<VsqNrpn>( generatePitchBendSensitivityNRPN( vsq, track, ms_presend_for_pitch ) );
2222- while ( listpbs.Count > 0 && listpbs[0].Clock < 0 ) {
2223- listpbs.RemoveAt( 0 );
2235+ List<VsqNrpn> listpbs = new List<VsqNrpn>( generatePitchBendSensitivityNRPN( vsq, track, ms_presend ) );
2236+ int index = 0;
2237+ while ( index < listpbs.Count ) {
2238+ if ( listpbs[index].Nrpn == NRPN.CC_PBS_PITCH_BEND_SENSITIVITY && listpbs[index].Clock < 0 ) {
2239+ listpbs.RemoveAt( index );
2240+ continue;
2241+ } else if ( listpbs[index].Nrpn == NRPN.CC_PBS_VERSION_AND_DEVICE && listpbs[index].Clock < 0 ) {
2242+ listpbs[index].Clock = 0;
2243+ } else if ( listpbs[index].Nrpn == NRPN.CC_PBS_DELAY && listpbs[index].Clock < 0 ) {
2244+ listpbs[index].Clock = 0;
2245+ }
2246+ index++;
22242247 }
22252248 if ( listpbs.Count > 0 ) {
22262249 list.AddRange( listpbs );
@@ -2228,11 +2251,20 @@
22282251 }
22292252 VsqBPList pit = vsq.Track[track].getCurve( "pit" );
22302253 if ( pit.getCount() > 0 ) {
2231- List<VsqNrpn> listpit = new List<VsqNrpn>( generatePitchBendNRPN( vsq, track, ms_presend_for_pitch ) );
2232- while( listpit.Count > 0 && listpit[0].Clock < 0 ){
2233- listpit.RemoveAt( 0 );
2254+ List<VsqNrpn> listpit = new List<VsqNrpn>( generatePitchBendNRPN( vsq, track, ms_presend ) );
2255+ int index = 0;
2256+ while ( index < listpit.Count ) {
2257+ if ( listpit[index].Nrpn == NRPN.PB_PITCH_BEND && listpit[index].Clock < 0 ) {
2258+ listpit.RemoveAt( index );
2259+ continue;
2260+ } else if ( listpit[index].Nrpn == NRPN.PB_VERSION_AND_DEVICE && listpit[index].Clock < 0 ) {
2261+ listpit[index].Clock = 0;
2262+ } else if ( listpit[index].Nrpn == NRPN.PB_DELAY && listpit[index].Clock < 0 ) {
2263+ listpit[index].Clock = 0;
2264+ }
2265+ index++;
22342266 }
2235- if ( listpit.Count > 0 ){
2267+ if ( listpit.Count > 0 ) {
22362268 list.AddRange( listpit );
22372269 }
22382270 }
--- trunk/Boare.Lib.Media/WaveReader.cs (revision 161)
+++ trunk/Boare.Lib.Media/WaveReader.cs (revision 162)
@@ -40,7 +40,7 @@
4040 if ( m_opened ) {
4141 m_stream.Close();
4242 }
43- m_stream = new FileStream( file, FileMode.Open );
43+ m_stream = new FileStream( file, FileMode.Open, FileAccess.Read );
4444
4545 // RIFF
4646 byte[] buf = new byte[4];
--- trunk/GenerateKeySound/Program.cs (revision 161)
+++ trunk/GenerateKeySound/Program.cs (revision 162)
@@ -189,7 +189,8 @@
189189 false,
190190 new string[] { },
191191 0.0,
192- false );
192+ false,
193+ "" );
193194 }
194195 }
195196 }
--- trunk/bocoree/misc.cs (revision 161)
+++ trunk/bocoree/misc.cs (revision 162)
@@ -121,13 +121,13 @@
121121 private static StreamWriter s_debug_out = null;
122122 private static string s_path = "";
123123
124- public static void force_logfile_path( string path ) {
124+ /*public static void force_logfile_path( string path ) {
125125 if ( s_debug_out != null ) {
126126 s_debug_out.Close();
127127 s_debug_out = new StreamWriter( path );
128128 }
129129 s_path = path;
130- }
130+ }*/
131131
132132 public static void push_log( string s ) {
133133 if ( s_debug_out == null ) {
--- trunk/PlaySound/PlaySound.cpp (nonexistent)
+++ trunk/PlaySound/PlaySound.cpp (revision 162)
@@ -0,0 +1,528 @@
1+/*
2+ * waveplay.cpp
3+ * Copyright (c) 2009 kbinani
4+ *
5+ * This file is part of Boare.Cadencii.
6+ *
7+ * Boare.Cadencii is free software; you can redistribute it and/or
8+ * modify it under the terms of the BSD License.
9+ *
10+ * Boare.Cadencii is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+ */
14+//#define TEST 1
15+#include "PlaySound.h"
16+
17+int waveplay::s_block_size = 44100;
18+int waveplay::s_sample_rate = 44100;
19+HWAVEOUT waveplay::s_hwave_out;
20+WAVEFORMATEX waveplay::s_wave_formatx;
21+WAVEHDR waveplay::s_wave_header[waveplay::_NUM_BUF];
22+unsigned long* waveplay::s_wave[waveplay::_NUM_BUF];
23+bool waveplay::s_done[waveplay::_NUM_BUF];
24+bool waveplay::s_abort_required = false;
25+int waveplay::s_buffer_loc = 0;
26+int waveplay::s_current_buffer = 0;
27+unsigned int waveplay::s_processed_count = 0;
28+bool waveplay::s_playing = false;
29+int waveplay::s_error_samples = 0;
30+int waveplay::s_last_buffer = -1;
31+FirstBufferWrittenCallback waveplay::s_first_buffer_written_callback;
32+double *waveplay::s_wave_buffer_l;
33+double *waveplay::s_wave_buffer_r;
34+
35+#ifdef TEST
36+ofstream debug::logger;
37+#endif
38+
39+bool waveplay::change_block_size( int block_size ){
40+ if ( s_playing ){
41+ return false;
42+ }
43+ if( block_size <= 0 ){
44+ return false;
45+ }
46+
47+ for( int k = 0; k < _NUM_BUF; k++ ){
48+ if( s_wave[k] ) delete [] s_wave[k];
49+ s_wave[k] = (unsigned long*)calloc( sizeof( unsigned long ), block_size );
50+ s_wave_header[k].lpData = (char*)s_wave[k];
51+ s_wave_header[k].dwBufferLength = sizeof( unsigned long ) * block_size;
52+ }
53+
54+ // s_wave_buffer_l, s_wave_buffer_rは、NULLならばon_your_markで初期化されるので、開放だけやっておけばOK
55+ if( s_wave_buffer_l ) delete [] s_wave_buffer_l;
56+ if( s_wave_buffer_r ) delete [] s_wave_buffer_r;
57+ // s_another_wave_l, s_another_wave_rは、on_your_markで全自動で初期化されるので特に操作の必要なし
58+ s_block_size = block_size;
59+ return true;
60+}
61+
62+void waveplay::terminate(){
63+ if( s_hwave_out ){
64+ waveOutReset( s_hwave_out );
65+#ifdef TEST
66+#ifdef __cplusplus_cli
67+ System::Console::WriteLine( "waveplay::terminate; waveOutReset" );
68+#else
69+ cout << "waveplay::terminate; waveOutReset" << endl;
70+#endif
71+#endif
72+ for( int k = 0; k < _NUM_BUF; k++ ){
73+ waveOutUnprepareHeader( s_hwave_out, &s_wave_header[k], sizeof( WAVEHDR ) );
74+ }
75+ waveOutClose( s_hwave_out );
76+ }
77+ for( int i = 0; i < _NUM_BUF; i++ ){
78+ if( s_wave[i] ){
79+ delete [] s_wave[i];
80+ }
81+ }
82+};
83+
84+void waveplay::set_first_buffer_written_callback( FirstBufferWrittenCallback proc ){
85+#ifdef TEST
86+#ifdef __cplusplus_cli
87+ debug::push_log( "waveplay::set_first_buffer_written_callback" );
88+#else
89+ debug::logger << "waveplay::set_first_buffer_wirtten_callback" << endl;
90+#endif
91+#endif
92+ s_first_buffer_written_callback = proc;
93+};
94+
95+void waveplay::reset(){
96+ s_playing = false;
97+ s_abort_required = true;
98+ if( s_hwave_out ){
99+ for( int k = 0; k < _NUM_BUF; k++ ){
100+ s_wave_header[k].dwUser = 1;
101+ }
102+ waveOutReset( s_hwave_out );
103+ unsigned long zero = MAKELONG( 0, 0 );
104+ for( int k = 0; k < _NUM_BUF; k++ ){
105+ for( int i = 0; i < s_block_size; i++ ){
106+ s_wave[k][i] = zero;
107+ }
108+ }
109+ }
110+};
111+
112+//todo: lengthがs_block_sizeよりも大きい場合の処理。
113+void waveplay::append( double** data, unsigned int length, double amp_left, double amp_right ){
114+ append_cor( data, length, amp_left, amp_right, false );
115+}
116+
117+void waveplay::flush_and_exit( double amp_left, double amp_right ){
118+ append_cor( (double**)0, 0, amp_left, amp_right, true );
119+}
120+
121+void waveplay::append_cor( double** a_data, unsigned int length, double amp_left, double amp_right, bool is_last_mode ){
122+#ifdef TEST
123+ debug::logger << "append_cor *************************************************************" << endl;
124+#endif
125+ s_playing = true;
126+ int jmax = length;
127+ int remain = 0;
128+ double **data = new double*[2];
129+ bool cleaning_required = false;
130+ if( s_error_samples > 0 ){
131+ if( s_error_samples >= length ){
132+ s_error_samples -= length;
133+ return;
134+ }
135+ cleaning_required = true;
136+ int actual_length = length - s_error_samples;
137+ data[0] = new double[actual_length];
138+ data[1] = new double[actual_length];
139+ for( int i = 0; i < actual_length; i++ ){
140+ data[0][i] = a_data[0][i + s_error_samples];
141+ data[1][i] = a_data[1][i + s_error_samples];
142+ }
143+ s_error_samples = 0;
144+ length = actual_length;
145+ jmax = length;
146+ }else{
147+ data = a_data;
148+ }
149+
150+ if( length + s_buffer_loc >= s_block_size ){
151+ jmax = s_block_size - s_buffer_loc;
152+ remain = length - jmax;
153+ }
154+ double aright = amp_right;
155+ double aleft = amp_left;
156+
157+ /*while( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) == WHDR_INQUEUE ){
158+ if( s_abort_required ){
159+ s_abort_required = false;
160+ goto clean_and_exit;
161+ }
162+ }*/
163+ for( int j = 0; j < jmax; j++ ){
164+ s_wave_buffer_l[j + s_buffer_loc] = data[1][j];
165+ s_wave_buffer_r[j + s_buffer_loc] = data[0][j];
166+ }
167+ s_buffer_loc += jmax;
168+
169+ if( s_buffer_loc >= s_block_size ){
170+ // バッファー充填完了.バッファーを転送し、waveOutWriteが書き込めるタイミングまで待機
171+#ifdef TEST
172+ debug::logger << "append_cor; waiting(1) " << s_current_buffer << "..." << endl;
173+#endif
174+ while( true ){
175+ if( s_abort_required ){
176+ s_abort_required = false;
177+ goto clean_and_exit;
178+ }
179+ //if( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) != WHDR_INQUEUE ){
180+ if( s_done[s_current_buffer] ){
181+ break;
182+ }
183+ }
184+#ifdef TEST
185+ debug::logger << "append_cor; ...exit" << endl;
186+#endif
187+
188+ s_processed_count++;
189+ mix( s_processed_count, aleft, aright );
190+
191+ if( s_processed_count == _NUM_BUF ){
192+ s_done[0] = false;
193+ MMRESULT ret = waveOutWrite( s_hwave_out, &s_wave_header[0], sizeof( WAVEHDR ) );
194+ if( s_first_buffer_written_callback ){
195+#ifdef TEST
196+ debug::logger << "append_cor; calling s_first_buffer_written_callback" << endl;
197+#endif
198+ s_first_buffer_written_callback();
199+ }
200+ for( int buffer_index = 1; buffer_index < _NUM_BUF; buffer_index++ ){
201+ s_done[buffer_index] = false;
202+ MMRESULT ret2 = waveOutWrite( s_hwave_out, &s_wave_header[buffer_index], sizeof( WAVEHDR ) );
203+ }
204+ s_current_buffer = _NUM_BUF - 1;
205+ }else if( s_processed_count > _NUM_BUF ){
206+ s_done[s_current_buffer] = false;
207+ MMRESULT ret3 = waveOutWrite( s_hwave_out, &s_wave_header[s_current_buffer], sizeof( WAVEHDR ) );
208+ }
209+ s_current_buffer++;
210+ if( s_current_buffer >= _NUM_BUF ){
211+ s_current_buffer = 0;
212+ }
213+
214+ s_buffer_loc = 0;
215+ }
216+
217+ if( remain > 0 ){
218+#ifdef TEST
219+ //debug::push_log( "append_cor; waiting(2) " + s_current_buffer + "..." );
220+#endif
221+ //while( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) == WHDR_INQUEUE ){
222+ /*while( !s_done[s_current_buffer] ){
223+#ifdef TEST
224+ for( int k = 0; k < _NUM_BUF; k++ ){
225+ //debug::push_log( "append_cor; " + s_done[k] );
226+ }
227+#endif
228+ if( s_abort_required ){
229+ s_abort_required = false;
230+ goto clean_and_exit;
231+ }
232+ }*/
233+#ifdef TEST
234+ //debug::push_log( "append_cor; ...exit" );
235+#endif
236+ for( int j = jmax; j < length; j++ ){
237+ s_wave_buffer_l[j - jmax] = data[1][j];
238+ s_wave_buffer_r[j - jmax] = data[0][j];
239+ }
240+ if( is_last_mode ){
241+ for( int j = length - jmax; j < s_block_size; j++ ){
242+ s_wave_buffer_l[j] = 0.0f;
243+ s_wave_buffer_r[j] = 0.0f;
244+ }
245+ }
246+ s_buffer_loc = remain;
247+ }
248+
249+#ifdef TEST
250+#ifdef __cplusplus_cli
251+ System::Console::WriteLine( "append_cor; is_last_mode=" + is_last_mode );
252+#endif
253+#endif
254+ if( is_last_mode ){
255+ if( s_processed_count < _NUM_BUF ){
256+ // _NUM_BUFブロック分のデータを未だ全て受信していない場合。バッファが未だひとつも書き込まれていないので
257+ // 0番のブロックから順に書き込む
258+ s_processed_count++;
259+ mix( s_processed_count, aleft, aright );
260+ s_done[0] = false;
261+ waveOutWrite( s_hwave_out, &s_wave_header[0], sizeof( WAVEHDR ) );
262+ if( s_first_buffer_written_callback ){
263+#ifdef TEST
264+#ifdef __cplusplus_cli
265+ debug::push_log( "append_cor; calling s_first_buffer_written_callback" );
266+#else
267+ debug::logger << "append_cor; calling s_first_buffer_written_callback" << endl;
268+#endif
269+#endif
270+ s_first_buffer_written_callback();
271+ }
272+ for( int i = 1; i < _NUM_BUF - 1; i++ ){
273+ s_processed_count++;
274+ mix( s_processed_count, aleft, aright );
275+ s_done[i] = false;
276+ waveOutWrite( s_hwave_out, &s_wave_header[i], sizeof( WAVEHDR ) );
277+ }
278+ }
279+ unsigned long zero = MAKELONG( 0, 0 );
280+ for( int j = s_buffer_loc; j < s_block_size; j++ ){
281+ s_wave_buffer_l[j] = 0.0f;
282+ s_wave_buffer_r[j] = 0.0f;
283+ }
284+#ifdef TEST
285+ debug::logger << "append_cor; waiting(3) " << s_current_buffer << "..." << endl;
286+#endif
287+ while( !s_done[s_current_buffer] ){
288+ //while( (s_wave_header[s_current_buffer].dwFlags & WHDR_INQUEUE) == WHDR_INQUEUE ){
289+ if( s_abort_required ){
290+ s_abort_required = false;
291+ goto clean_and_exit;
292+ }
293+ }
294+#ifdef TEST
295+ debug::logger << "append_cor; ...exit" << endl;
296+#endif
297+ s_processed_count++;
298+ mix( s_processed_count, aleft, aright );
299+ s_done[s_current_buffer] = false;
300+ MMRESULT ret4 = waveOutWrite( s_hwave_out, &s_wave_header[s_current_buffer], sizeof( WAVEHDR ) );
301+ }
302+clean_and_exit:
303+ if( is_last_mode ){
304+ s_last_buffer = s_current_buffer;
305+ }
306+ if( cleaning_required ){
307+ delete [] data[0];
308+ delete [] data[1];
309+ delete [] data;
310+ }
311+};
312+
313+void waveplay::mix( int processed_count, float amp_left, float amp_right ){
314+ int current_buffer = (processed_count - 1) % _NUM_BUF;
315+ for( int i = 0; i < s_block_size; i++ ){
316+ float l = s_wave_buffer_l[i] * amp_left;
317+ float r = s_wave_buffer_r[i] * amp_right;
318+ s_wave[current_buffer][i] = MAKELONG( (unsigned short)(r * 32768.0f), (unsigned short)(l * 32768.0f) );
319+ }
320+}
321+
322+void waveplay::on_your_mark(){
323+ for( int k = 0; k < _NUM_BUF; k++ ){
324+ s_wave_header[k].dwUser = 0;
325+ s_done[k] = true;
326+ }
327+ s_abort_required = false;
328+ s_buffer_loc = 0;
329+ s_current_buffer = 0;
330+ s_processed_count = 0;
331+ s_playing = true;
332+ s_last_buffer = -1;
333+
334+ if( !s_wave_buffer_l ){
335+ s_wave_buffer_l = new double[s_block_size];
336+ }
337+ if( !s_wave_buffer_r ){
338+ s_wave_buffer_r = new double[s_block_size];
339+ }
340+}
341+
342+double waveplay::get_play_time(){
343+ if( s_playing ){
344+ MMTIME mmt;
345+ mmt.wType = TIME_MS;
346+ waveOutGetPosition( s_hwave_out, &mmt, sizeof( MMTIME ) );
347+ float ms = 0.0;
348+ switch( mmt.wType ){
349+ case TIME_MS:
350+ return mmt.u.ms * 0.001;
351+ break;
352+ case TIME_SAMPLES:
353+ return (double)mmt.u.sample / (double)s_wave_formatx.nSamplesPerSec;
354+ case TIME_BYTES:
355+ return (double)mmt.u.cb / (double)s_wave_formatx.nAvgBytesPerSec;
356+ default:
357+ return -1.0;
358+ }
359+ return 0.0;
360+ }else{
361+ return -1.0;
362+ }
363+};
364+
365+void waveplay::init( int block_size, int sample_rate ){
366+ s_block_size = block_size;
367+ s_sample_rate = sample_rate;
368+
369+ s_wave_formatx.wFormatTag = WAVE_FORMAT_PCM;
370+ s_wave_formatx.nChannels = 2;
371+ s_wave_formatx.wBitsPerSample = 16;
372+ s_wave_formatx.nBlockAlign = s_wave_formatx.nChannels * s_wave_formatx.wBitsPerSample / 8;
373+ s_wave_formatx.nSamplesPerSec = s_sample_rate;
374+ s_wave_formatx.nAvgBytesPerSec = s_wave_formatx.nSamplesPerSec * s_wave_formatx.nBlockAlign;
375+
376+ waveOutOpen( &s_hwave_out, WAVE_MAPPER, &s_wave_formatx, (unsigned long)wave_callback, 0, CALLBACK_FUNCTION );
377+
378+ for( int k = 0; k < _NUM_BUF; k++ ){
379+ s_wave[k] = (unsigned long*)calloc( sizeof( unsigned long ), s_block_size );
380+ s_wave_header[k].lpData = (char*)s_wave[k];
381+ s_wave_header[k].dwBufferLength = sizeof( unsigned long ) * s_block_size;
382+ s_wave_header[k].dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
383+ s_wave_header[k].dwLoops = 1;
384+
385+ waveOutPrepareHeader( s_hwave_out, &s_wave_header[k], sizeof( WAVEHDR ) );
386+ s_wave_header[k].dwUser = 0;
387+ }
388+};
389+
390+void waveplay::abort(){
391+ s_abort_required = true;
392+ reset();
393+ for( int k = 0; k < _NUM_BUF; k++ ){
394+ if( s_wave[k] ){
395+ memset( s_wave[k], 0, s_block_size * sizeof( unsigned long ) );
396+ }
397+ }
398+ s_buffer_loc = 0;
399+ s_current_buffer = 0;
400+ s_processed_count = 0;
401+};
402+
403+void CALLBACK waveplay::wave_callback( HWAVEOUT hwo, unsigned int uMsg, unsigned long dwInstance, unsigned long dwParam1, unsigned long dwParam2 ){
404+ if ( uMsg == MM_WOM_DONE ){
405+ int index_done = 0;
406+ for( int k = 0; k < _NUM_BUF; k++ ){
407+ if( (LPWAVEHDR)dwParam1 == &s_wave_header[k] ){
408+ index_done = k;
409+#ifdef TEST
410+#ifdef __cplusplus_cli
411+ System::DateTime ^now = System::DateTime::Now;
412+ System::String ^nowstr = now->Day + " " + now->Hour + ":" + now->Minute + ":" + (double)(now->Second + now->Millisecond / 1000.0);
413+ System::Console::WriteLine( "waveplay::wave_callback; now=" + nowstr + "; done=" + index_done + "; last_buffer=" + s_last_buffer + "; dwUser=" + s_wave_header[k].dwUser );
414+#else
415+ std::cout << "waveplay::wave_callback; done=" << index_done << std::endl;
416+#endif
417+#endif
418+ s_done[index_done] = true;
419+ if( s_last_buffer == index_done ){
420+ s_playing = false;
421+ }
422+ if( s_wave_header[k].dwUser != 0 ){
423+ s_wave_header[k].dwUser = 0;
424+ }
425+ break;
426+ }
427+ }
428+ }
429+ return;
430+}
431+
432+#ifdef __cplusplus_cli
433+System::String ^waveplay::util_get_errmsg( MMRESULT msg ){
434+ wchar_t err[260];
435+ mciGetErrorStringW( msg, err, 260 );
436+#else
437+string waveplay::util_get_errmsg( MMRESULT msg ){
438+ char err[260];
439+ mciGetErrorStringA( msg, err, 260 );
440+#endif
441+ int len = 260;
442+ for( int i = 1; i < 260; i++ ){
443+ if( err[i] == '\0' ){
444+ len = i - 1;
445+ break;
446+ }
447+ }
448+#ifdef __cplusplus_cli
449+ array<wchar_t> ^errstr = gcnew array<wchar_t>( len );
450+ for( int i = 0; i < len; i++ ){
451+ errstr[i] = err[i];
452+ }
453+ return gcnew System::String( errstr, 0, len );
454+#else
455+ string ret( err );
456+ return ret;
457+#endif
458+};
459+
460+bool waveplay::is_alive(){
461+ return s_playing;
462+};
463+
464+extern "C" {
465+ void SoundInit( int block_size, int sample_rate ){
466+ waveplay::init( block_size, sample_rate );
467+ }
468+
469+ void SoundAppend( double *left, double *right, int length ){
470+ if( !waveplay::is_alive() ){
471+ waveplay::on_your_mark();
472+ }
473+ double *out[] = { left, right };
474+ waveplay::append( out, length, 1.0, 1.0 );
475+ }
476+
477+ void SoundReset(){
478+ waveplay::abort();
479+ }
480+
481+ double SoundGetPosition(){
482+ if( waveplay::is_alive() ){
483+ return waveplay::get_play_time();
484+ }else{
485+ return 0.0;
486+ }
487+ }
488+
489+ bool SoundIsBusy(){
490+ return waveplay::is_alive();
491+ }
492+
493+ void SoundWaitForExit(){
494+ if( waveplay::is_alive() ){
495+ waveplay::flush_and_exit( 1.0, 1.0 );
496+ }
497+ while( waveplay::is_alive() ){
498+ }
499+ }
500+}
501+
502+int main(){
503+ debug::logger.open( "test.log", ios::out );
504+ const int sample_rate = 48000;
505+
506+ int f = 200;
507+ int len = sample_rate / f; //波長
508+ double *left = new double[sample_rate];
509+ double *right = new double[sample_rate];
510+ for( int i = 0; i < sample_rate; i++ ){ //波形データ作成
511+ if( i % len < len / 2 ){
512+ left[i] = 0.2f;
513+ right[i] = 0.2f;
514+ }else{
515+ left[i] = -0.2f;
516+ right[i] = -0.2f;
517+ }
518+ }
519+
520+ std::cout << "is_alive=" << (waveplay::is_alive() ? "True" : "False") << endl;
521+
522+ SoundInit( sample_rate, sample_rate );
523+ for( int i = 0; i < 5; i++ ){
524+ SoundAppend( left, right, sample_rate );
525+ }
526+ SoundWaitForExit();
527+ return 0;
528+}
--- trunk/PlaySound/PlaySound.h (nonexistent)
+++ trunk/PlaySound/PlaySound.h (revision 162)
@@ -0,0 +1,98 @@
1+/*
2+ * waveplay.h
3+ * Copyright (c) 2009 kbinani
4+ *
5+ * This file is part of Boare.Cadencii.
6+ *
7+ * Boare.Cadencii is free software; you can redistribute it and/or
8+ * modify it under the terms of the BSD License.
9+ *
10+ * Boare.Cadencii is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13+ */
14+#ifndef __PlaySound_h__
15+#define __PlaySound_h__
16+
17+#include <iostream>
18+#include <string>
19+#include <windows.h>
20+#include <fstream>
21+#pragma comment(lib, "winmm.lib")
22+
23+#define TEST
24+
25+using namespace std;
26+
27+// 最初のバッファが書き込まれたとき呼び出されるコールバック関数
28+typedef void (*FirstBufferWrittenCallback)();
29+
30+class debug{
31+public:
32+ static ofstream logger;
33+};
34+
35+class waveplay{
36+private:
37+ static const int _NUM_BUF = 3; // バッファの数
38+ static int s_block_size; // 1個のバッファのサイズ(サンプル)
39+ static int s_sample_rate; // サンプリングレート
40+ static WAVEFORMATEX s_wave_formatx; // WAVEファイルヘッダ
41+ static HWAVEOUT s_hwave_out; // WAVE再生デバイス
42+ static WAVEHDR s_wave_header[_NUM_BUF];// WAVEヘッダ
43+ static unsigned long* s_wave[_NUM_BUF]; // バッファ
44+ static bool s_done[_NUM_BUF];
45+ static int s_current_buffer; // 次回書き込むべきバッファのインデクス
46+ static unsigned int s_processed_count; // 初回はバッファを_NUM_BUF個全部埋めなければいけないので、最初の _NUM_BUF + 1 回はカウントを行う。そのためのカウンタ
47+ static bool s_abort_required; // 再生の中断が要求された時立つフラグ
48+ static int s_buffer_loc; // 書き込み中のバッファ内の、現在位置
49+ static bool s_playing; // 再生中かどうかを表すフラグ
50+ static int s_error_samples; // appendされた波形データの内、先頭のs_error_samples分を省く。通常の使い方なら常に0だが、vocaloid2 vstiで使う場合、プリセンド分を除いてwaveOutWriteしなければいけないので非0になる。
51+ static int s_last_buffer; // 最後に再生されるバッファの番号。負値の場合、append_lastが未だ呼ばれていないことを意味する。
52+ static double *s_wave_buffer_l;
53+ static double *s_wave_buffer_r;
54+ static FirstBufferWrittenCallback s_first_buffer_written_callback; // 最初のバッファが書き込まれたとき呼び出されるコールバック関数
55+
56+ /// コールバック関数
57+ static void CALLBACK wave_callback( HWAVEOUT hwo, unsigned int uMsg, unsigned long dwInstance, unsigned long dwParam1, unsigned long dwParam2 );
58+ static void append_cor( double** a_data, unsigned int length, double amp_left, double amp_right, bool is_last_mode );
59+ static void mix( int processed_count, float amp_left, float amp_right );
60+#ifdef __cplusplus_cli
61+ static System::String ^waveplay::util_get_errmsg( MMRESULT msg );
62+#else
63+ static string waveplay::util_get_errmsg( MMRESULT msg );
64+#endif
65+public:
66+ static void on_your_mark();
67+ /// 初期化関数
68+ static void init( int block_size, int sample_rate );
69+ /// 波形データをバッファに追加する。バッファが再生中などの理由で即座に書き込めない場合、バッファが書き込み可能となるまで待機させられる
70+ static void append( double** data, unsigned int length, double amp_left, double amp_right );
71+ static void flush_and_exit( double amp_left, double amp_right );
72+ /// 再生中断を要求する
73+ static void abort();
74+ /// 現在の再生位置を取得する。再生中でない場合負の値となる。
75+ static double get_play_time();
76+ /// リセットする。abort関数でも呼び出される。
77+ static void reset();
78+ /// コールバック関数を設定する
79+ static void set_first_buffer_written_callback( FirstBufferWrittenCallback proc );
80+ static void terminate();
81+ /// 現在再生中かどうかを取得する
82+ static bool is_alive();
83+ /// ブロックサイズを変更します
84+ static bool change_block_size( int block_size );
85+};
86+
87+extern "C" {
88+
89+ void SoundInit( int block_size, int sample_rate );
90+ void SoundAppend( double *left, double *right, int length );
91+ void SoundReset();
92+ double SoundGetPosition();
93+ bool SoundIsBusy();
94+ void SoundWaitForExit();
95+
96+}
97+
98+#endif // __PlaySound_h__
旧リポジトリブラウザで表示