(メッセージはありません)
@@ -167,6 +167,9 @@ | ||
167 | 167 | string temp_dir = Path.Combine( Path.GetDirectoryName( script ), Path.GetFileNameWithoutExtension( script ) ); |
168 | 168 | |
169 | 169 | #if DEBUG |
170 | + if ( !Directory.Exists( temp_dir ) ) { | |
171 | + Directory.CreateDirectory( temp_dir ); | |
172 | + } | |
170 | 173 | StreamWriter sw = new StreamWriter( Path.Combine( temp_dir, "log.txt" ) ); |
171 | 174 | #endif |
172 | 175 | // 原音設定を読み込み |
@@ -885,7 +885,8 @@ | ||
885 | 885 | } |
886 | 886 | int sa_rendered_last = 0; // どこまでレンダリングが済んでいるか。 |
887 | 887 | 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; | |
889 | 890 | sa_rendered_last = sa_from_ms( ms_rendered_last ); |
890 | 891 | } |
891 | 892 | #ifdef _TEST |
@@ -896,7 +897,7 @@ | ||
896 | 897 | while( sa_to > sa_rendered_last && m_last_rendered[track] + 1 < m_events[track].size() ){ |
897 | 898 | m_last_rendered[track] = m_last_rendered[track] + 1; |
898 | 899 | int last = m_last_rendered[track]; |
899 | - // このループ内では,m_events[m_last_rendered]がレンダリングされる | |
900 | + // このループ内では,m_events[m_last_rendered[track]]がレンダリングされる | |
900 | 901 | m_current_singer = m_events[track][last].Program; |
901 | 902 | if( m_current_singer < 0 || g_singers.size() <= m_current_singer ){ |
902 | 903 | // 範囲外の場合、とりあえず0にして歌わせる |
@@ -926,12 +927,12 @@ | ||
926 | 927 | oss << track << "_" << last << ".wav"; |
927 | 928 | string filename = oss.str(); |
928 | 929 | 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; | |
930 | 931 | m_events[track][last].msActualLength = actual_msec; |
931 | 932 | m_events[track][last].Result = path_combine( g_temp_dir, filename ); |
932 | 933 | m_events[track][last].msActualTime = m_events[track][last].msTime - oa.msPreUtterance; |
933 | 934 | oss.str( "" ); |
934 | - oss << (int)(actual_msec + 50); //ここの50は一定? | |
935 | + oss << actual_msec + 50; //ここの50は一定? | |
935 | 936 | string millisec = oss.str(); |
936 | 937 | oss.str( "" ); |
937 | 938 | string flags = m_events[track][last].get_flags() + "L"; |
@@ -1291,6 +1292,10 @@ | ||
1291 | 1292 | dat.read( wavbuf, buflen ); |
1292 | 1293 | int len = dat.gcount(); |
1293 | 1294 | if( len <= 0 ){ |
1295 | + dat.close(); | |
1296 | +#ifdef _TEST | |
1297 | + g_logger << "BAIL-OUT" << endl; | |
1298 | +#endif | |
1294 | 1299 | goto fillzero; |
1295 | 1300 | } |
1296 | 1301 | int count = 0; |
@@ -1310,6 +1315,10 @@ | ||
1310 | 1315 | dat.read( wavbuf, buflen ); |
1311 | 1316 | int len = dat.gcount(); |
1312 | 1317 | if( len <= 0 ){ |
1318 | + dat.close(); | |
1319 | +#ifdef _TEST | |
1320 | + g_logger << "BAIL-OUT" << endl; | |
1321 | +#endif | |
1313 | 1322 | goto fillzero; |
1314 | 1323 | } |
1315 | 1324 | int count = 0; |
@@ -1330,6 +1339,10 @@ | ||
1330 | 1339 | dat.read( wavbuf, buflen ); |
1331 | 1340 | int len = dat.gcount(); |
1332 | 1341 | if( len <= 0 ){ |
1342 | + dat.close(); | |
1343 | +#ifdef _TEST | |
1344 | + g_logger << "BAIL-OUT" << endl; | |
1345 | +#endif | |
1333 | 1346 | goto fillzero; |
1334 | 1347 | } |
1335 | 1348 | int count = 0; |
@@ -1350,6 +1363,10 @@ | ||
1350 | 1363 | dat.read( wavbuf, buflen ); |
1351 | 1364 | int len = dat.gcount(); |
1352 | 1365 | if( len <= 0 ){ |
1366 | + dat.close(); | |
1367 | +#ifdef _TEST | |
1368 | + g_logger << "BAIL-OUT" << endl; | |
1369 | +#endif | |
1353 | 1370 | goto fillzero; |
1354 | 1371 | } |
1355 | 1372 | int count = 0; |
@@ -23,7 +23,7 @@ | ||
23 | 23 | #endif |
24 | 24 | |
25 | 25 | //#define USE_DOUBLE |
26 | -#define TEST | |
26 | +//#define TEST | |
27 | 27 | |
28 | 28 | namespace Boare{ namespace Cadencii{ |
29 | 29 |
@@ -123,13 +123,6 @@ | ||
123 | 123 | namespace Boare{ namespace Cadencii{ |
124 | 124 | |
125 | 125 | #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 | - } | |
133 | 126 | #else |
134 | 127 | AEffect *vstidrv::s_aeffect; // 読込んだdllから作成したVOCALOID2の本体。VOCALOID2への操作はs_aeffect->dispatcherで行う |
135 | 128 | MIDI_EVENT **vstidrv::s_track_events; // 受信したmidiイベントのリスト。s_track_events[0]はvsqのマスタートラックのtempo情報のみを格納 |
@@ -195,7 +188,7 @@ | ||
195 | 188 | if( s_track_events ){ |
196 | 189 | delete [] s_track_events; |
197 | 190 | } |
198 | - waveplay::terminate(); | |
191 | +// waveplay::terminate(); | |
199 | 192 | //TODO: g_hwave_outの終了処理 |
200 | 193 | #ifdef TEST |
201 | 194 | #ifdef __cplusplus_cli |
@@ -372,8 +365,8 @@ | ||
372 | 365 | |
373 | 366 | g_block_size = block_size; |
374 | 367 | 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 ); | |
377 | 370 | |
378 | 371 | #ifdef __cplusplus_cli |
379 | 372 | WCHAR *str = new WCHAR[dll_path->Length + 1]; |
@@ -568,13 +561,7 @@ | ||
568 | 561 | int vstidrv::StartRendering( |
569 | 562 | __int64 total_samples, |
570 | 563 | 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 | |
578 | 565 | #else |
579 | 566 | int vstidrv::StartRendering( |
580 | 567 | __int64 total_samples, |
@@ -663,44 +650,7 @@ | ||
663 | 650 | #endif |
664 | 651 | |
665 | 652 | 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 | - } | |
675 | 653 | 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 | - }*/ | |
704 | 654 | |
705 | 655 | MIDI_EVENT* pWork = s_track_events[1]; |
706 | 656 | //int eof_clock = 0; |
@@ -742,9 +692,6 @@ | ||
742 | 692 | delete [] left_ch; |
743 | 693 | delete [] right_ch; |
744 | 694 | free_events( lpEvents ); |
745 | - if( direct_play_enabled ){ | |
746 | - waveplay::abort(); | |
747 | - } | |
748 | 695 | exit_start_rendering(); |
749 | 696 | return FALSE; |
750 | 697 | } |
@@ -882,9 +829,6 @@ | ||
882 | 829 | delete [] left_ch; |
883 | 830 | delete [] right_ch; |
884 | 831 | free_events( lpEvents ); |
885 | - if( direct_play_enabled ){ | |
886 | - waveplay::abort(); | |
887 | - } | |
888 | 832 | exit_start_rendering(); |
889 | 833 | return FALSE; |
890 | 834 | } |
@@ -913,16 +857,6 @@ | ||
913 | 857 | } |
914 | 858 | |
915 | 859 | 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 ){ | |
926 | 860 | #ifdef __cplusplus_cli |
927 | 861 | array<Double> ^send_data_l = gcnew array<Double>( dwFrames ); |
928 | 862 | array<Double> ^send_data_r = gcnew array<Double>( dwFrames ); |
@@ -945,7 +879,6 @@ | ||
945 | 879 | #ifdef TEST |
946 | 880 | Console::WriteLine( " ...done" ); |
947 | 881 | #endif |
948 | - } | |
949 | 882 | total_processed += dwFrames; |
950 | 883 | } else { |
951 | 884 | dwDeltaDelay += iOffset; |
@@ -971,9 +904,6 @@ | ||
971 | 904 | while( dwDelta ){ |
972 | 905 | if ( g_cancelRequired ) { |
973 | 906 | free_events( lpEvents ); |
974 | - if( direct_play_enabled ){ | |
975 | - waveplay::abort(); | |
976 | - } | |
977 | 907 | exit_start_rendering(); |
978 | 908 | return FALSE; |
979 | 909 | } |
@@ -984,10 +914,6 @@ | ||
984 | 914 | s_aeffect->processReplacing( s_aeffect, NULL, out_buffer, dwFrames ); |
985 | 915 | #endif |
986 | 916 | |
987 | - if( direct_play_enabled ){ | |
988 | - waveplay::append( out_buffer, dwFrames, amplify_left, amplify_right ); | |
989 | - } | |
990 | - if( event_enabled ){ | |
991 | 917 | #ifdef __cplusplus_cli |
992 | 918 | array<Double> ^send_data_l = gcnew array<Double>( dwFrames ); |
993 | 919 | array<Double> ^send_data_r = gcnew array<Double>( dwFrames ); |
@@ -1004,7 +930,6 @@ | ||
1004 | 930 | #else |
1005 | 931 | s_wave_incoming_callback( send_data_l, send_data_r, dwFrames ); |
1006 | 932 | #endif |
1007 | - } | |
1008 | 933 | |
1009 | 934 | dwDelta -= dwFrames; |
1010 | 935 | total_processed += dwFrames; |
@@ -1019,33 +944,8 @@ | ||
1019 | 944 | std::cout << "vstidrv::StartRendering; total_processed=" << total_processed << std::endl; |
1020 | 945 | #endif |
1021 | 946 | #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 | - | |
1037 | 947 | free_events( lpEvents ); |
1038 | 948 | |
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 | - | |
1049 | 949 | delete [] left_ch; |
1050 | 950 | delete [] right_ch; |
1051 | 951 | #ifdef __cplusplus_cli |
@@ -1065,74 +965,13 @@ | ||
1065 | 965 | |
1066 | 966 | void vstidrv::AbortRendering(){ |
1067 | 967 | g_cancelRequired = true; |
1068 | - waveplay::abort(); | |
968 | +// waveplay::abort(); | |
1069 | 969 | }; |
1070 | 970 | |
1071 | 971 | double vstidrv::GetProgress(){ |
1072 | 972 | return g_progress; |
1073 | 973 | }; |
1074 | - | |
1075 | - float vstidrv::GetPlayTime(){ | |
1076 | - return waveplay::get_play_time(); | |
1077 | - }; | |
1078 | 974 | |
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 | - | |
1136 | 975 | vstidrv::vstidrv(){ |
1137 | 976 | #ifdef TEST |
1138 | 977 | #ifdef __cplusplus_cli |
@@ -247,12 +247,6 @@ | ||
247 | 247 | float aright = (float)amp_right; |
248 | 248 | float aleft = (float)amp_left; |
249 | 249 | |
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 | - }*/ | |
256 | 250 | for( int j = 0; j < jmax; j++ ){ |
257 | 251 | s_wave_buffer_l[j + s_buffer_loc] = data[1][j]; |
258 | 252 | s_wave_buffer_r[j + s_buffer_loc] = data[0][j]; |
@@ -308,24 +302,6 @@ | ||
308 | 302 | } |
309 | 303 | |
310 | 304 | 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 | |
329 | 305 | for( int j = jmax; j < length; j++ ){ |
330 | 306 | s_wave_buffer_l[j - jmax] = data[1][j]; |
331 | 307 | s_wave_buffer_r[j - jmax] = data[0][j]; |
@@ -15,7 +15,7 @@ | ||
15 | 15 | #define __vstidrv3_h__ |
16 | 16 | #include "stdafx.h" |
17 | 17 | #include "winmmhelp.h" |
18 | -#include "waveplay.h" | |
18 | +//#include "waveplay.h" | |
19 | 19 | #include "pluginterfaces/vst2.x/aeffectx.h" |
20 | 20 | |
21 | 21 | #ifdef __cplusplus_cli |
@@ -159,7 +159,7 @@ | ||
159 | 159 | #ifdef __cplusplus_cli |
160 | 160 | virtual event WaveIncomingEventHandler ^WaveIncoming; |
161 | 161 | virtual event RenderingFinishedEventHandler ^RenderingFinished; |
162 | - virtual void SetFirstBufferWrittenCallback( Boare::Lib::Media::FirstBufferWrittenCallback ^handler ); | |
162 | + //virtual void SetFirstBufferWrittenCallback( Boare::Lib::Media::FirstBufferWrittenCallback ^handler ); | |
163 | 163 | #else |
164 | 164 | static void SetFirstBufferWrittenCallback( FirstBufferWrittenCallback proc ); |
165 | 165 | static void SetWaveIncomingCallback( WaveIncomingCallback proc ); |
@@ -179,13 +179,7 @@ | ||
179 | 179 | virtual int StartRendering( |
180 | 180 | __int64 total_samples, |
181 | 181 | 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 ); | |
189 | 183 | #else |
190 | 184 | static int StartRendering( |
191 | 185 | __int64 total_samples, |
@@ -200,32 +194,8 @@ | ||
200 | 194 | bool mode_infinite ); |
201 | 195 | #endif |
202 | 196 | __PFX_INTERFACE__ void AbortRendering(); |
203 | - __PFX_INTERFACE__ double GetProgress(); | |
204 | - __PFX_INTERFACE__ float GetPlayTime(); | |
205 | - __PFX_INTERFACE__ void WaveOutReset(); | |
197 | + __PFX_INTERFACE__ double GetProgress(); | |
206 | 198 | __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(); | |
229 | 199 | }; |
230 | 200 | |
231 | 201 | } } |
@@ -22,6 +22,7 @@ | ||
22 | 22 | using System.Xml.Serialization; |
23 | 23 | using System.CodeDom.Compiler; |
24 | 24 | using Microsoft.CSharp; |
25 | +using System.Text; | |
25 | 26 | |
26 | 27 | using Boare.Lib.Vsq; |
27 | 28 | /* |
@@ -60,6 +61,8 @@ | ||
60 | 61 | /// AttachedCurve用のシリアライザ |
61 | 62 | /// </summary> |
62 | 63 | public static XmlSerializer XmlSerializerListBezierCurves = new XmlSerializer( typeof( AttachedCurve ) ); |
64 | + public static string PathResampler = ""; | |
65 | + public static string PathWavtool = ""; | |
63 | 66 | |
64 | 67 | #region Static Readonly Fields |
65 | 68 | public static readonly Color[] s_HILIGHT = new Color[] { |
@@ -115,7 +118,7 @@ | ||
115 | 118 | private static SolidBrush s_hilight_brush = new SolidBrush( Color.CornflowerBlue ); |
116 | 119 | private static object s_locker; |
117 | 120 | private static Boare.Lib.AppUtil.XmlSerializeWithDescription s_serizlizer = null; |
118 | - private static UtauSingerConfigSys s_utau_singers; | |
121 | + public static UtauSingerConfigSys UtauSingers; | |
119 | 122 | #endregion |
120 | 123 | |
121 | 124 | public delegate void MainFormClosedEventHandler( EditorManager manager ); |
@@ -522,18 +525,27 @@ | ||
522 | 525 | } |
523 | 526 | } |
524 | 527 | 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 | + } | |
526 | 538 | } else { |
527 | - s_utau_singers = null; | |
539 | + UtauSingers = null; | |
528 | 540 | } |
529 | 541 | } |
530 | 542 | |
531 | 543 | 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 ) ); | |
534 | 546 | } |
535 | - if ( s_utau_singers != null ) { | |
536 | - return s_utau_singers.getSingerConfigs(); | |
547 | + if ( UtauSingers != null ) { | |
548 | + return UtauSingers.getSingerConfigs(); | |
537 | 549 | } else { |
538 | 550 | return new Dictionary<int, SingerConfig>(); |
539 | 551 | } |
@@ -540,11 +552,11 @@ | ||
540 | 552 | } |
541 | 553 | |
542 | 554 | 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 ) ); | |
545 | 557 | } |
546 | - if ( s_utau_singers != null ) { | |
547 | - return s_utau_singers.getSingerID( program_change ); | |
558 | + if ( UtauSingers != null ) { | |
559 | + return UtauSingers.getSingerID( program_change ); | |
548 | 560 | } else { |
549 | 561 | VsqID ret = new VsqID( 0 ); |
550 | 562 | ret.IconHandle = new IconHandle(); |
@@ -558,11 +570,11 @@ | ||
558 | 570 | } |
559 | 571 | |
560 | 572 | 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 ) ); | |
563 | 575 | } |
564 | - if ( s_utau_singers != null ) { | |
565 | - return s_utau_singers.getSingerInfo( program_change ); | |
576 | + if ( UtauSingers != null ) { | |
577 | + return UtauSingers.getSingerInfo( program_change ); | |
566 | 578 | } else { |
567 | 579 | return null; |
568 | 580 | } |
@@ -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 | +} |
@@ -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 | +} |
@@ -38,9 +38,7 @@ | ||
38 | 38 | private const int _SAMPLE_RATE = 44100; |
39 | 39 | private const int _BLOCK_SIZE = 44100; |
40 | 40 | |
41 | - //private static string s_dll_path = ""; | |
42 | 41 | public static string CurrentUser = ""; |
43 | - //private static bool s_loaded = false; | |
44 | 42 | private static WaveWriter s_wave; |
45 | 43 | private static bool s_rendering = false; |
46 | 44 | private static int s_trim_remain = 0; |
@@ -49,7 +47,8 @@ | ||
49 | 47 | private static double s_amplify_right = 1.0; |
50 | 48 | private static string s_working_renderer = ""; |
51 | 49 | 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; | |
53 | 52 | |
54 | 53 | private class StartRenderArg { |
55 | 54 | public string renderer; |
@@ -64,6 +63,17 @@ | ||
64 | 63 | public bool mode_infinite; |
65 | 64 | } |
66 | 65 | |
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 | + | |
67 | 77 | private class VstiRenderer { |
68 | 78 | #if UNMANAGED_VSTIDRV |
69 | 79 | public vstildr DllInstance = null; |
@@ -73,7 +83,7 @@ | ||
73 | 83 | public bool Loaded = false; |
74 | 84 | public string Path = ""; |
75 | 85 | public string Name = ""; |
76 | - public volatile Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWrittenEventHandler = null; | |
86 | + //public volatile Boare.Lib.Media.FirstBufferWrittenCallback FirstBufferWrittenEventHandler = null; | |
77 | 87 | } |
78 | 88 | |
79 | 89 | static VSTiProxy() { |
@@ -85,6 +95,7 @@ | ||
85 | 95 | if ( Environment.OSVersion.Platform == PlatformID.Unix ) { |
86 | 96 | return; |
87 | 97 | } |
98 | + PlaySound.Init( _BLOCK_SIZE, _SAMPLE_RATE ); | |
88 | 99 | #if !DEBUG |
89 | 100 | try { |
90 | 101 | #endif |
@@ -130,7 +141,7 @@ | ||
130 | 141 | vocalo2_dll_path = ""; |
131 | 142 | } |
132 | 143 | string vocalo1_dll_path = VocaloSysUtil.getDllPathVsti1(); |
133 | - string utauvsti_dll_path = AppManager.EditorConfig.PathUtauVSTi; | |
144 | + //string utauvsti_dll_path = AppManager.EditorConfig.PathUtauVSTi; | |
134 | 145 | if ( vocalo2_dll_path != "" && File.Exists( vocalo2_dll_path ) ) { |
135 | 146 | VstiRenderer vr = new VstiRenderer(); |
136 | 147 | vr.Path = vocalo2_dll_path; |
@@ -147,7 +158,7 @@ | ||
147 | 158 | vr.Name = RENDERER_DSB2; |
148 | 159 | m_vstidrv.Add( vr ); |
149 | 160 | } |
150 | - if ( utauvsti_dll_path != "" && File.Exists( utauvsti_dll_path ) ) { | |
161 | + /*if ( utauvsti_dll_path != "" && File.Exists( utauvsti_dll_path ) ) { | |
151 | 162 | VstiRenderer vr = new VstiRenderer(); |
152 | 163 | vr.Path = utauvsti_dll_path; |
153 | 164 | vr.Loaded = false; |
@@ -154,7 +165,7 @@ | ||
154 | 165 | vr.DllInstance = (vstildr)asm.CreateInstance( driver_fullname ); |
155 | 166 | vr.Name = RENDERER_UTU0; |
156 | 167 | m_vstidrv.Add( vr ); |
157 | - } | |
168 | + }*/ | |
158 | 169 | #else |
159 | 170 | string vocalo2_dll_path = VocaloSysUtil.getDllPathVsti2(); |
160 | 171 | string vocalo1_dll_path = VocaloSysUtil.getDllPathVsti1(); |
@@ -201,14 +212,11 @@ | ||
201 | 212 | string dll_path = m_vstidrv[i].Path; |
202 | 213 | bool loaded = false; |
203 | 214 | try { |
204 | -#if TEST | |
205 | - //s_dll_path = @"C:\Program Files\Steinberg\VSTplugins\utauvsti\utauvsti.dll"; | |
206 | -#endif | |
207 | 215 | char[] str = dll_path.ToCharArray(); |
208 | 216 | if ( dll_path != "" ) { |
209 | 217 | 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 ); | |
212 | 220 | } else { |
213 | 221 | loaded = false; |
214 | 222 | } |
@@ -235,6 +243,12 @@ | ||
235 | 243 | return true; |
236 | 244 | } |
237 | 245 | } |
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 | + } | |
238 | 252 | return false; |
239 | 253 | } |
240 | 254 |
@@ -242,9 +256,9 @@ | ||
242 | 256 | #if TEST |
243 | 257 | bocoree.debug.push_log( "VSTiProxy.HandleFirstBufferWrittenEvent" ); |
244 | 258 | #endif |
245 | - if ( FirstBufferWritten != null ) { | |
259 | + /*if ( FirstBufferWritten != null ) { | |
246 | 260 | FirstBufferWritten(); |
247 | - } | |
261 | + }*/ | |
248 | 262 | } |
249 | 263 | |
250 | 264 | public static int SampleRate { |
@@ -287,7 +301,8 @@ | ||
287 | 301 | bool direct_play, |
288 | 302 | string[] files, |
289 | 303 | double wave_read_offset_seconds, |
290 | - bool mode_infinite | |
304 | + bool mode_infinite, | |
305 | + string temp_dir | |
291 | 306 | ) { |
292 | 307 | #if TEST |
293 | 308 | Common.DebugWriteLine( "VSTiProxy+Render" ); |
@@ -294,6 +309,7 @@ | ||
294 | 309 | Common.DebugWriteLine( " start_sec,end_sec=" + start_sec + "," + end_sec ); |
295 | 310 | #endif |
296 | 311 | s_working_renderer = VSTiProxy.RENDERER_DSB3; |
312 | + s_direct_play = direct_play; | |
297 | 313 | string version = vsq.Track[track].getCommon().Version; |
298 | 314 | if ( version.StartsWith( VSTiProxy.RENDERER_DSB2 ) ) { |
299 | 315 | s_working_renderer = VSTiProxy.RENDERER_DSB2; |
@@ -332,34 +348,64 @@ | ||
332 | 348 | long total_samples = (long)((end_sec - start_sec) * _SAMPLE_RATE); |
333 | 349 | int trim_msec = (int)(trim_sec * 1000.0); |
334 | 350 | 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; | |
346 | 361 | |
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 | + } | |
350 | 382 | } 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 | + } | |
363 | 409 | } |
364 | 410 | } |
365 | 411 |
@@ -379,10 +425,26 @@ | ||
379 | 425 | sra.mode_infinite ); |
380 | 426 | } |
381 | 427 | |
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 | + | |
382 | 443 | public static void WaveOutReset() { |
383 | 444 | for ( int i = 0; i < m_vstidrv.Count; i++ ) { |
384 | 445 | if ( m_vstidrv[i].Loaded ) { |
385 | - m_vstidrv[i].DllInstance.WaveOutReset(); | |
446 | + //m_vstidrv[i].DllInstance.WaveOutReset(); | |
447 | + PlaySound.Reset(); | |
386 | 448 | } |
387 | 449 | } |
388 | 450 | } |
@@ -405,6 +467,7 @@ | ||
405 | 467 | Console.WriteLine( "VSTiProxy.RenderToWave( NRPN[], TempoTableEntry[], int, string )" ); |
406 | 468 | bocoree.debug.push_log( "VSTiPRoxy+RenderToWave(NrpnData[], TempoTableEntry[], int, string)" ); |
407 | 469 | #endif |
470 | + s_direct_play = direct_play; | |
408 | 471 | int index_driver = -1; |
409 | 472 | for ( int i = 0; i < m_vstidrv.Count; i++ ) { |
410 | 473 | if ( m_vstidrv[i].Name == renderer ) { |
@@ -445,10 +508,7 @@ | ||
445 | 508 | masterEventsSrc[count + 1] = b1; |
446 | 509 | masterEventsSrc[count + 2] = b2; |
447 | 510 | } |
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 ); | |
452 | 512 | |
453 | 513 | int numEvents = nrpn.Length; |
454 | 514 | byte[] bodyEventsSrc = new byte[numEvents * 3]; |
@@ -478,14 +538,10 @@ | ||
478 | 538 | #if DEBUG |
479 | 539 | Common.DebugWriteLine( " s_trim_remain=" + s_trim_remain ); |
480 | 540 | #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 ); | |
485 | 542 | |
486 | 543 | s_rendering = true; |
487 | 544 | if ( file != null ) { |
488 | - //s_wave = new WaveWriter( file, WaveChannel.Stereo, 16, _SAMPLE_RATE ); | |
489 | 545 | s_wave = file; |
490 | 546 | if ( s_trim_remain < 0 ) { |
491 | 547 | double[] d = new double[-s_trim_remain]; |
@@ -503,27 +559,22 @@ | ||
503 | 559 | |
504 | 560 | s_amplify_left = amplify_left; |
505 | 561 | s_amplify_right = amplify_right; |
506 | - if ( file != null ) { | |
562 | + //if ( file != null ) { | |
507 | 563 | m_vstidrv[index_driver].DllInstance.WaveIncoming += vstidrv_WaveIncoming; |
508 | - } | |
564 | + //} | |
509 | 565 | 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 | |
519 | 571 | while ( s_rendering ) { |
520 | 572 | Application.DoEvents(); |
521 | 573 | } |
522 | 574 | s_rendering = false; |
523 | - if ( file != null ) { | |
575 | + //if ( file != null ) { | |
524 | 576 | m_vstidrv[index_driver].DllInstance.WaveIncoming -= vstidrv_WaveIncoming; |
525 | - //s_wave.Close(); | |
526 | - } | |
577 | + //} | |
527 | 578 | m_vstidrv[index_driver].DllInstance.RenderingFinished -= vstidrv_RenderingFinished; |
528 | 579 | s_wave = null; |
529 | 580 | } |
@@ -532,22 +583,15 @@ | ||
532 | 583 | s_rendering = false; |
533 | 584 | } |
534 | 585 | |
535 | - static void vstidrv_WaveIncoming( double[] L, double[] R ) { | |
586 | + static unsafe void vstidrv_WaveIncoming( double[] L, double[] R ) { | |
536 | 587 | #if TEST |
537 | 588 | bocoree.debug.push_log( "VSTiProxy.vstidrv_WaveIncoming" ); |
538 | 589 | bocoree.debug.push_log( " requiring lock of s_locker..." ); |
539 | 590 | #endif |
540 | 591 | 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 | |
545 | 592 | if ( s_trim_remain > 0 ) { |
546 | 593 | if ( s_trim_remain >= L.Length ) { |
547 | 594 | s_trim_remain -= L.Length; |
548 | -#if TEST | |
549 | - //bocoree.debug.push_log( " ...lock released" ); | |
550 | -#endif | |
551 | 595 | return; |
552 | 596 | } |
553 | 597 | int actual_append = L.Length - s_trim_remain; |
@@ -557,10 +601,15 @@ | ||
557 | 601 | dL[i] = L[i + s_trim_remain] * s_amplify_left; |
558 | 602 | dR[i] = R[i + s_trim_remain] * s_amplify_right; |
559 | 603 | } |
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 | + } | |
564 | 613 | dL = null; |
565 | 614 | dR = null; |
566 | 615 | s_trim_remain = 0; |
@@ -571,14 +620,19 @@ | ||
571 | 620 | for ( int i = 0; i < R.Length; i++ ) { |
572 | 621 | R[i] = R[i] * s_amplify_right; |
573 | 622 | } |
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 | + } | |
578 | 632 | } |
579 | 633 | } |
580 | -#if TEST | |
581 | - bocoree.debug.push_log( " ...lock released" ); | |
634 | +#if DEBUG | |
635 | + bocoree.debug.push_log( "...done" ); | |
582 | 636 | #endif |
583 | 637 | } |
584 | 638 |
@@ -595,9 +649,13 @@ | ||
595 | 649 | if ( s_rendering ) { |
596 | 650 | s_rendering = false; |
597 | 651 | } |
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 | + } | |
601 | 659 | } |
602 | 660 | } |
603 | 661 | } |
@@ -615,12 +673,11 @@ | ||
615 | 673 | } |
616 | 674 | |
617 | 675 | 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; | |
624 | 681 | } |
625 | 682 | |
626 | 683 | #if OBSOLUTE |
@@ -750,7 +750,6 @@ | ||
750 | 750 | #endif |
751 | 751 | } |
752 | 752 | if ( si.EditVsqDelegate != null ) { |
753 | - m_manager.BgmPlayer.UnLoad(); | |
754 | 753 | VsqFileEx old = (VsqFileEx)m_manager.VsqFile.Clone(); |
755 | 754 | if ( m_manager.InvokeScript( si ) ) { |
756 | 755 | Edited = true; |
@@ -46,6 +46,7 @@ | ||
46 | 46 | this.menuFileSaveNamed = new System.Windows.Forms.ToolStripMenuItem(); |
47 | 47 | this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripSeparator(); |
48 | 48 | this.menuFileImport = new System.Windows.Forms.ToolStripMenuItem(); |
49 | + this.menuFileImportVsq = new System.Windows.Forms.ToolStripMenuItem(); | |
49 | 50 | this.menuFileImportUst = new System.Windows.Forms.ToolStripMenuItem(); |
50 | 51 | this.menuFileImportMidi = new System.Windows.Forms.ToolStripMenuItem(); |
51 | 52 | this.menuFileExport = new System.Windows.Forms.ToolStripMenuItem(); |
@@ -265,6 +266,7 @@ | ||
265 | 266 | this.vScroll = new Boare.Lib.AppUtil.BVScrollBar(); |
266 | 267 | this.hScroll = new Boare.Lib.AppUtil.BHScrollBar(); |
267 | 268 | this.picturePositionIndicator = new System.Windows.Forms.PictureBox(); |
269 | + this.pictPianoRoll = new Boare.Cadencii.BPictureBox(); | |
268 | 270 | this.pictureBox3 = new System.Windows.Forms.PictureBox(); |
269 | 271 | this.pictureBox2 = new System.Windows.Forms.PictureBox(); |
270 | 272 | this.toolStripTool = new System.Windows.Forms.ToolStrip(); |
@@ -294,6 +296,7 @@ | ||
294 | 296 | this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator(); |
295 | 297 | this.stripDDBtnSpeed = new System.Windows.Forms.ToolStripDropDownButton(); |
296 | 298 | this.panel2 = new System.Windows.Forms.Panel(); |
299 | + this.waveView = new Boare.Cadencii.WaveView(); | |
297 | 300 | this.splitContainer2 = new Boare.Lib.AppUtil.BSplitContainer(); |
298 | 301 | this.splitContainer1 = new Boare.Lib.AppUtil.BSplitContainer(); |
299 | 302 | this.toolStripPosition = new System.Windows.Forms.ToolStrip(); |
@@ -348,9 +351,6 @@ | ||
348 | 351 | this.openUstDialog = new System.Windows.Forms.OpenFileDialog(); |
349 | 352 | this.openMidiDialog = new System.Windows.Forms.OpenFileDialog(); |
350 | 353 | 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(); | |
354 | 354 | this.menuStripMain.SuspendLayout(); |
355 | 355 | this.cMenuPiano.SuspendLayout(); |
356 | 356 | this.cMenuTrackTab.SuspendLayout(); |
@@ -358,6 +358,7 @@ | ||
358 | 358 | ((System.ComponentModel.ISupportInitialize)(this.trackBar)).BeginInit(); |
359 | 359 | this.panel1.SuspendLayout(); |
360 | 360 | ((System.ComponentModel.ISupportInitialize)(this.picturePositionIndicator)).BeginInit(); |
361 | + ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).BeginInit(); | |
361 | 362 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit(); |
362 | 363 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); |
363 | 364 | this.toolStripTool.SuspendLayout(); |
@@ -370,7 +371,6 @@ | ||
370 | 371 | this.toolStripPosition.SuspendLayout(); |
371 | 372 | this.toolStripMeasure.SuspendLayout(); |
372 | 373 | this.toolStripFile.SuspendLayout(); |
373 | - ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).BeginInit(); | |
374 | 374 | this.SuspendLayout(); |
375 | 375 | // |
376 | 376 | // menuStripMain |
@@ -416,7 +416,7 @@ | ||
416 | 416 | // |
417 | 417 | this.menuFileNew.Name = "menuFileNew"; |
418 | 418 | 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 ); | |
420 | 420 | this.menuFileNew.Text = "New(N)"; |
421 | 421 | this.menuFileNew.Click += new System.EventHandler( this.commonFileNew_Click ); |
422 | 422 | // |
@@ -424,7 +424,7 @@ | ||
424 | 424 | // |
425 | 425 | this.menuFileOpen.Name = "menuFileOpen"; |
426 | 426 | 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 ); | |
428 | 428 | this.menuFileOpen.Text = "Open(&O)"; |
429 | 429 | this.menuFileOpen.Click += new System.EventHandler( this.commonFileOpen_Click ); |
430 | 430 | // |
@@ -432,7 +432,7 @@ | ||
432 | 432 | // |
433 | 433 | this.menuFileSave.Name = "menuFileSave"; |
434 | 434 | 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 ); | |
436 | 436 | this.menuFileSave.Text = "Save(&S)"; |
437 | 437 | this.menuFileSave.Click += new System.EventHandler( this.commonFileSave_Click ); |
438 | 438 | // |
@@ -439,7 +439,7 @@ | ||
439 | 439 | // menuFileSaveNamed |
440 | 440 | // |
441 | 441 | this.menuFileSaveNamed.Name = "menuFileSaveNamed"; |
442 | - this.menuFileSaveNamed.Size = new System.Drawing.Size( 152, 22 ); | |
442 | + this.menuFileSaveNamed.Size = new System.Drawing.Size( 151, 22 ); | |
443 | 443 | this.menuFileSaveNamed.Text = "Save As(&A)"; |
444 | 444 | this.menuFileSaveNamed.Click += new System.EventHandler( this.menuFileSaveNamed_Click ); |
445 | 445 | // |
@@ -446,7 +446,7 @@ | ||
446 | 446 | // toolStripMenuItem10 |
447 | 447 | // |
448 | 448 | this.toolStripMenuItem10.Name = "toolStripMenuItem10"; |
449 | - this.toolStripMenuItem10.Size = new System.Drawing.Size( 149, 6 ); | |
449 | + this.toolStripMenuItem10.Size = new System.Drawing.Size( 148, 6 ); | |
450 | 450 | // |
451 | 451 | // menuFileImport |
452 | 452 | // |
@@ -455,9 +455,16 @@ | ||
455 | 455 | this.menuFileImportUst, |
456 | 456 | this.menuFileImportMidi} ); |
457 | 457 | this.menuFileImport.Name = "menuFileImport"; |
458 | - this.menuFileImport.Size = new System.Drawing.Size( 152, 22 ); | |
458 | + this.menuFileImport.Size = new System.Drawing.Size( 151, 22 ); | |
459 | 459 | this.menuFileImport.Text = "Import(&I)"; |
460 | 460 | // |
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 | + // | |
461 | 468 | // menuFileImportUst |
462 | 469 | // |
463 | 470 | this.menuFileImportUst.Name = "menuFileImportUst"; |
@@ -478,7 +485,7 @@ | ||
478 | 485 | this.menuFileExportWave, |
479 | 486 | this.menuFileExportMidi} ); |
480 | 487 | this.menuFileExport.Name = "menuFileExport"; |
481 | - this.menuFileExport.Size = new System.Drawing.Size( 152, 22 ); | |
488 | + this.menuFileExport.Size = new System.Drawing.Size( 151, 22 ); | |
482 | 489 | this.menuFileExport.Text = "Export(&E)"; |
483 | 490 | this.menuFileExport.DropDownOpening += new System.EventHandler( this.menuFileExport_DropDownOpening ); |
484 | 491 | // |
@@ -485,7 +492,7 @@ | ||
485 | 492 | // menuFileExportWave |
486 | 493 | // |
487 | 494 | this.menuFileExportWave.Name = "menuFileExportWave"; |
488 | - this.menuFileExportWave.Size = new System.Drawing.Size( 152, 22 ); | |
495 | + this.menuFileExportWave.Size = new System.Drawing.Size( 97, 22 ); | |
489 | 496 | this.menuFileExportWave.Text = "Wave"; |
490 | 497 | this.menuFileExportWave.Click += new System.EventHandler( this.menuFileExportWave_Click ); |
491 | 498 | // |
@@ -492,7 +499,7 @@ | ||
492 | 499 | // menuFileExportMidi |
493 | 500 | // |
494 | 501 | this.menuFileExportMidi.Name = "menuFileExportMidi"; |
495 | - this.menuFileExportMidi.Size = new System.Drawing.Size( 152, 22 ); | |
502 | + this.menuFileExportMidi.Size = new System.Drawing.Size( 97, 22 ); | |
496 | 503 | this.menuFileExportMidi.Text = "MIDI"; |
497 | 504 | this.menuFileExportMidi.Click += new System.EventHandler( this.menuFileExportMidi_Click ); |
498 | 505 | // |
@@ -499,24 +506,24 @@ | ||
499 | 506 | // toolStripMenuItem11 |
500 | 507 | // |
501 | 508 | this.toolStripMenuItem11.Name = "toolStripMenuItem11"; |
502 | - this.toolStripMenuItem11.Size = new System.Drawing.Size( 149, 6 ); | |
509 | + this.toolStripMenuItem11.Size = new System.Drawing.Size( 148, 6 ); | |
503 | 510 | // |
504 | 511 | // menuFileRecent |
505 | 512 | // |
506 | 513 | this.menuFileRecent.Name = "menuFileRecent"; |
507 | - this.menuFileRecent.Size = new System.Drawing.Size( 152, 22 ); | |
514 | + this.menuFileRecent.Size = new System.Drawing.Size( 151, 22 ); | |
508 | 515 | this.menuFileRecent.Text = "Recent Files(&R)"; |
509 | 516 | // |
510 | 517 | // toolStripMenuItem12 |
511 | 518 | // |
512 | 519 | this.toolStripMenuItem12.Name = "toolStripMenuItem12"; |
513 | - this.toolStripMenuItem12.Size = new System.Drawing.Size( 149, 6 ); | |
520 | + this.toolStripMenuItem12.Size = new System.Drawing.Size( 148, 6 ); | |
514 | 521 | // |
515 | 522 | // menuFileQuit |
516 | 523 | // |
517 | 524 | this.menuFileQuit.Name = "menuFileQuit"; |
518 | 525 | 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 ); | |
520 | 527 | this.menuFileQuit.Text = "Quit(&Q)"; |
521 | 528 | this.menuFileQuit.Click += new System.EventHandler( this.menuFileQuit_Click ); |
522 | 529 | // |
@@ -1261,6 +1268,7 @@ | ||
1261 | 1268 | this.menuSettingBgm.Name = "menuSettingBgm"; |
1262 | 1269 | this.menuSettingBgm.Size = new System.Drawing.Size( 200, 22 ); |
1263 | 1270 | this.menuSettingBgm.Text = "BGM(&B)"; |
1271 | + this.menuSettingBgm.Visible = false; | |
1264 | 1272 | // |
1265 | 1273 | // menuSettingBgmSetSound |
1266 | 1274 | // |
@@ -1397,7 +1405,7 @@ | ||
1397 | 1405 | this.tToolStripMenuItem.Size = new System.Drawing.Size( 264, 22 ); |
1398 | 1406 | this.tToolStripMenuItem.Text = "t"; |
1399 | 1407 | // |
1400 | - // saveVsqDialog | |
1408 | + // saveXmlVsqDialog | |
1401 | 1409 | // |
1402 | 1410 | this.saveXmlVsqDialog.Filter = "VSQ Format(*.vsq)|*.vsq|Original Format(*.evsq)|*.evsq|All files(*.*)|*.*"; |
1403 | 1411 | // |
@@ -1847,7 +1855,7 @@ | ||
1847 | 1855 | this.cMenuPianoVibratoProperty.Text = "Note Vibrato Property"; |
1848 | 1856 | this.cMenuPianoVibratoProperty.Click += new System.EventHandler( this.cMenuPianoVibratoProperty_Click ); |
1849 | 1857 | // |
1850 | - // openVsqDialog | |
1858 | + // openXmlVsqDialog | |
1851 | 1859 | // |
1852 | 1860 | this.openXmlVsqDialog.Filter = "VSQ Format(*.vsq)|*.vsq|Original Format(*.evsq)|*.evsq"; |
1853 | 1861 | // |
@@ -2227,6 +2235,28 @@ | ||
2227 | 2235 | this.picturePositionIndicator.Paint += new System.Windows.Forms.PaintEventHandler( this.picturePositionIndicator_Paint ); |
2228 | 2236 | this.picturePositionIndicator.MouseEnter += new System.EventHandler( this.picturePositionIndicator_MouseEnter ); |
2229 | 2237 | // |
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 | + // | |
2230 | 2260 | // pictureBox3 |
2231 | 2261 | // |
2232 | 2262 | this.pictureBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); |
@@ -2510,6 +2540,18 @@ | ||
2510 | 2540 | this.panel2.Size = new System.Drawing.Size( 421, 59 ); |
2511 | 2541 | this.panel2.TabIndex = 19; |
2512 | 2542 | // |
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 | + // | |
2513 | 2555 | // splitContainer2 |
2514 | 2556 | // |
2515 | 2557 | this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; |
@@ -3049,47 +3091,6 @@ | ||
3049 | 3091 | // |
3050 | 3092 | this.openUstDialog.Filter = "UTAU Project File(*.ust)|*.ust|All Files(*.*)|*.*"; |
3051 | 3093 | // |
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 | - // | |
3093 | 3094 | // FormMain |
3094 | 3095 | // |
3095 | 3096 | this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 12F ); |
@@ -3117,6 +3118,7 @@ | ||
3117 | 3118 | ((System.ComponentModel.ISupportInitialize)(this.trackBar)).EndInit(); |
3118 | 3119 | this.panel1.ResumeLayout( false ); |
3119 | 3120 | ((System.ComponentModel.ISupportInitialize)(this.picturePositionIndicator)).EndInit(); |
3121 | + ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).EndInit(); | |
3120 | 3122 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit(); |
3121 | 3123 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); |
3122 | 3124 | this.toolStripTool.ResumeLayout( false ); |
@@ -3137,7 +3139,6 @@ | ||
3137 | 3139 | this.toolStripMeasure.PerformLayout(); |
3138 | 3140 | this.toolStripFile.ResumeLayout( false ); |
3139 | 3141 | this.toolStripFile.PerformLayout(); |
3140 | - ((System.ComponentModel.ISupportInitialize)(this.pictPianoRoll)).EndInit(); | |
3141 | 3142 | this.ResumeLayout( false ); |
3142 | 3143 | this.PerformLayout(); |
3143 | 3144 |
@@ -855,11 +855,10 @@ | ||
855 | 855 | timer.Enabled = false; |
856 | 856 | VSTiProxy.AbortRendering(); |
857 | 857 | VSTiProxy.WaveOutReset(); |
858 | - m_manager.BgmPlayer.Stop(); | |
859 | 858 | for ( int i = 0; i < m_draw_start_index.Length; i++ ) { |
860 | 859 | m_draw_start_index[i] = 0; |
861 | 860 | } |
862 | - VSTiProxy.FirstBufferWritten -= vstidrv_FirstBufferWritten; | |
861 | + //VSTiProxy.FirstBufferWritten -= vstidrv_FirstBufferWritten; | |
863 | 862 | m_manager.FirstBufferWritten = false; |
864 | 863 | if ( m_midi_in != null ) { |
865 | 864 | m_midi_in.Stop(); |
@@ -1023,7 +1022,7 @@ | ||
1023 | 1022 | Common.DebugWriteLine( "m_preview_ending_time=" + m_preview_ending_time ); |
1024 | 1023 | #endif |
1025 | 1024 | |
1026 | - VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten; | |
1025 | + //VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten; | |
1027 | 1026 | |
1028 | 1027 | VSTiProxy.Render( m_manager.VsqFile, |
1029 | 1028 | selected, |
@@ -1036,7 +1035,8 @@ | ||
1036 | 1035 | true, |
1037 | 1036 | sounds.ToArray(), |
1038 | 1037 | m_direct_play_shift, |
1039 | - (m_manager.EditMode == EditMode.Realtime) ); | |
1038 | + (m_manager.EditMode == EditMode.Realtime), | |
1039 | + m_manager.TempWaveDir ); | |
1040 | 1040 | |
1041 | 1041 | for ( int i = 0; i < m_draw_start_index.Length; i++ ) { |
1042 | 1042 | m_draw_start_index[i] = 0; |
@@ -1044,7 +1044,7 @@ | ||
1044 | 1044 | int clock_now = m_manager.CurrentClock; |
1045 | 1045 | double sec_now = m_manager.VsqFile.getSecFromClock( clock_now ); |
1046 | 1046 | } else { |
1047 | - VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten; | |
1047 | + //VSTiProxy.FirstBufferWritten += vstidrv_FirstBufferWritten; | |
1048 | 1048 | VSTiProxy.Render( new VsqFile( 0, m_manager.VsqFile.getPreMeasure(), 4, 4, 500000 ), |
1049 | 1049 | 1, |
1050 | 1050 | null, |
@@ -1056,7 +1056,8 @@ | ||
1056 | 1056 | true, |
1057 | 1057 | sounds.ToArray(), |
1058 | 1058 | m_direct_play_shift, |
1059 | - (m_manager.EditMode == EditMode.Realtime) ); | |
1059 | + (m_manager.EditMode == EditMode.Realtime), | |
1060 | + m_manager.TempWaveDir ); | |
1060 | 1061 | } |
1061 | 1062 | } |
1062 | 1063 |
@@ -1068,6 +1069,7 @@ | ||
1068 | 1069 | } else { |
1069 | 1070 | m_manager.RendererAvailable = VSTiProxy.IsRendererAvailable( renderer ); |
1070 | 1071 | } |
1072 | + m_manager.FirstBufferWritten = true; | |
1071 | 1073 | m_last_ignitted = DateTime.Now; |
1072 | 1074 | m_manager.PreviewStartedTime = m_last_ignitted; |
1073 | 1075 | #if DEBUG |
@@ -1085,10 +1087,6 @@ | ||
1085 | 1087 | m_manager.FirstBufferWritten = true; |
1086 | 1088 | m_last_regulated = DateTime.Now; |
1087 | 1089 | 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 | - } | |
1092 | 1090 | } |
1093 | 1091 | |
1094 | 1092 | private void m_manager_SelectedToolChanged( object sender, EventArgs e ) { |
@@ -3841,7 +3839,7 @@ | ||
3841 | 3839 | using ( OpenFileDialog ofd = new OpenFileDialog() ) { |
3842 | 3840 | ofd.Filter = _( "MP3 File(*.mp3)|*.mp3" ) + "|" + _( "Wave File(*.wav)|*.wav" ) + "|" + _( "All Files(*.*)|*.*" ); |
3843 | 3841 | if ( ofd.ShowDialog() == DialogResult.OK ) { |
3844 | - m_manager.BgmPlayer.Load( ofd.FileName ); | |
3842 | + //m_manager.BgmPlayer.Load( ofd.FileName ); | |
3845 | 3843 | } |
3846 | 3844 | } |
3847 | 3845 | } |
@@ -209,6 +209,8 @@ | ||
209 | 209 | public RgbColor PianorollColorUtauBeat = new RgbColor( 128, 128, 255 ); |
210 | 210 | [XmlItemDescription( "Show actual pitch line or not" )] |
211 | 211 | public bool ViewAtcualPitch = false; |
212 | + [XmlItemDescription( "Invoke resampler with Wine" )] | |
213 | + public bool InvokeUtauCoreWithWine = false; | |
212 | 214 | |
213 | 215 | /// <summary> |
214 | 216 | /// PositionQuantize, PositionQuantizeTriplet, LengthQuantize, LengthQuantizeTripletの描くプロパティのいずれかが |
@@ -84,10 +84,6 @@ | ||
84 | 84 | /// </summary> |
85 | 85 | private PlayPositionSpecifier m_current_play_position; |
86 | 86 | /// <summary> |
87 | - /// BGMプレイヤ | |
88 | - /// </summary> | |
89 | - private MediaPlayer m_bgm_player = new MediaPlayer(); | |
90 | - /// <summary> | |
91 | 87 | /// プレビュー再生のスピード |
92 | 88 | /// </summary> |
93 | 89 | private float m_speed = 1.0f; |
@@ -180,7 +176,7 @@ | ||
180 | 176 | #if DEBUG |
181 | 177 | Common.DebugWriteLine( "EditorManager..ctor; log=" + log ); |
182 | 178 | #endif |
183 | - bocoree.debug.force_logfile_path( log ); | |
179 | + //bocoree.debug.force_logfile_path( log ); | |
184 | 180 | } |
185 | 181 | #endif |
186 | 182 | /// <summary> |
@@ -320,15 +316,6 @@ | ||
320 | 316 | } |
321 | 317 | } |
322 | 318 | |
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 | - | |
332 | 319 | public string TempWaveDir { |
333 | 320 | get { |
334 | 321 | string temp = Path.Combine( AppManager.ApplicationDataPath, _TEMPDIR_NAME ); |
@@ -142,7 +142,8 @@ | ||
142 | 142 | false, |
143 | 143 | new string[] { }, |
144 | 144 | 0.0, |
145 | - false ); | |
145 | + false, | |
146 | + m_manager.TempWaveDir ); | |
146 | 147 | } |
147 | 148 | } else { |
148 | 149 | for ( int i = 0; i < m_tracks.Length; i++ ) { |
@@ -174,7 +175,8 @@ | ||
174 | 175 | false, |
175 | 176 | new string[] { }, |
176 | 177 | 0.0, |
177 | - false ); | |
178 | + false, | |
179 | + m_manager.TempWaveDir ); | |
178 | 180 | } |
179 | 181 | } |
180 | 182 | } |
@@ -2200,11 +2200,8 @@ | ||
2200 | 2200 | if ( version.StartsWith( "DSB2" ) ) { |
2201 | 2201 | list.AddRange( generateFx2DepthNRPN( vsq, track, msPreSend ) ); |
2202 | 2202 | } |
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; | |
2208 | 2205 | if ( version.StartsWith( "UTU0" ) ) { |
2209 | 2206 | double sec_maxlen = 0.0; |
2210 | 2207 | for ( Iterator itr = vsq.Track[track].getNoteEventIterator(); itr.hasNext(); ) { |
@@ -2212,15 +2209,41 @@ | ||
2212 | 2209 | double len = vsq.getSecFromClock( ve.Clock + ve.ID.Length ) - vsq.getSecFromClock( ve.Clock ); |
2213 | 2210 | sec_maxlen = Math.Max( sec_maxlen, len ); |
2214 | 2211 | } |
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++; | |
2217 | 2228 | } |
2229 | + if ( listdyn.Count > 0 ) { | |
2230 | + list.AddRange( listdyn ); | |
2231 | + } | |
2218 | 2232 | } |
2219 | 2233 | VsqBPList pbs = vsq.Track[track].getCurve( "pbs" ); |
2220 | 2234 | 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++; | |
2224 | 2247 | } |
2225 | 2248 | if ( listpbs.Count > 0 ) { |
2226 | 2249 | list.AddRange( listpbs ); |
@@ -2228,11 +2251,20 @@ | ||
2228 | 2251 | } |
2229 | 2252 | VsqBPList pit = vsq.Track[track].getCurve( "pit" ); |
2230 | 2253 | 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++; | |
2234 | 2266 | } |
2235 | - if ( listpit.Count > 0 ){ | |
2267 | + if ( listpit.Count > 0 ) { | |
2236 | 2268 | list.AddRange( listpit ); |
2237 | 2269 | } |
2238 | 2270 | } |
@@ -40,7 +40,7 @@ | ||
40 | 40 | if ( m_opened ) { |
41 | 41 | m_stream.Close(); |
42 | 42 | } |
43 | - m_stream = new FileStream( file, FileMode.Open ); | |
43 | + m_stream = new FileStream( file, FileMode.Open, FileAccess.Read ); | |
44 | 44 | |
45 | 45 | // RIFF |
46 | 46 | byte[] buf = new byte[4]; |
@@ -189,7 +189,8 @@ | ||
189 | 189 | false, |
190 | 190 | new string[] { }, |
191 | 191 | 0.0, |
192 | - false ); | |
192 | + false, | |
193 | + "" ); | |
193 | 194 | } |
194 | 195 | } |
195 | 196 | } |
@@ -121,13 +121,13 @@ | ||
121 | 121 | private static StreamWriter s_debug_out = null; |
122 | 122 | private static string s_path = ""; |
123 | 123 | |
124 | - public static void force_logfile_path( string path ) { | |
124 | + /*public static void force_logfile_path( string path ) { | |
125 | 125 | if ( s_debug_out != null ) { |
126 | 126 | s_debug_out.Close(); |
127 | 127 | s_debug_out = new StreamWriter( path ); |
128 | 128 | } |
129 | 129 | s_path = path; |
130 | - } | |
130 | + }*/ | |
131 | 131 | |
132 | 132 | public static void push_log( string s ) { |
133 | 133 | if ( s_debug_out == null ) { |
@@ -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 | +} |
@@ -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__ |