오픈 소스 소프트웨어 개발 및 다운로드

Browse Subversion Repository

Contents of /trunk/Boare.Lib.Media/WavePlay.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations) (download)
Thu Jun 25 14:16:22 2009 UTC (14 years, 10 months ago) by kbinani
File size: 28929 byte(s)


1 /*
2 * WavePlay.cs
3 * Copyright (c) 2009 kbinani
4 *
5 * This file is part of Boare.Lib.Media.
6 *
7 * Boare.Lib.Media is free software; you can redistribute it and/or
8 * modify it under the terms of the BSD License.
9 *
10 * Boare.Lib.Media 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 using System;
15 using System.Runtime.InteropServices;
16
17 using bocoree;
18
19 namespace Boare.Lib.Media {
20
21 public delegate void FirstBufferWrittenCallback();
22
23 public unsafe class WavePlay {
24 const int _NUM_BUF = 3; // バッファの数
25 int s_block_size; // 1個のバッファのサイズ(サンプル)
26 int s_sample_rate; // サンプリングレート
27 WAVEFORMATEX s_wave_formatx; // WAVEファイルヘッダ
28 //IntPtr s_ptr_wave_formatx;
29 IntPtr s_hwave_out; // WAVE再生デバイス
30
31 WAVEHDR[] s_wave_header = new WAVEHDR[_NUM_BUF];// WAVEヘッダ
32 IntPtr[] s_ptr_wave_header = new IntPtr[_NUM_BUF];
33
34 uint*[] s_wave = new uint*[_NUM_BUF]; // バッファ
35 IntPtr[] s_ptr_wave = new IntPtr[_NUM_BUF];
36
37 bool[] s_done = new bool[_NUM_BUF];
38 int s_current_buffer; // 次回書き込むべきバッファのインデクス
39 uint s_processed_count; // 初回はバッファを_NUM_BUF個全部埋めなければいけないので、最初の _NUM_BUF + 1 回はカウントを行う。そのためのカウンタ
40 bool s_abort_required; // 再生の中断が要求された時立つフラグ
41 int s_buffer_loc; // 書き込み中のバッファ内の、現在位置
42 bool s_playing; // 再生中かどうかを表すフラグ
43 int s_error_samples; // appendされた波形データの内、先頭のs_error_samples分を省く。通常の使い方なら常に0だが、vocaloid2 vstiで使う場合、プリセンド分を除いてwaveOutWriteしなければいけないので非0になる。
44 int s_last_buffer; // 最後に再生されるバッファの番号。負値の場合、append_lastが未だ呼ばれていないことを意味する。
45 FirstBufferWrittenCallback s_first_buffer_written_callback; // 最初のバッファが書き込まれたとき呼び出されるコールバック関数
46 WaveReader[] s_wave_reader;
47 int s_num_wave_reader; // s_wave_readerの個数
48 float*[] s_another_wave_l;
49 IntPtr[] s_ptr_another_wave_l;
50 float*[] s_another_wave_r;
51 IntPtr[] s_ptr_another_wave_r;
52 long s_wave_read_offset_samples;
53 float* s_wave_buffer_l;
54 IntPtr s_ptr_wave_buffer_l;
55 float* s_wave_buffer_r;
56 IntPtr s_ptr_wave_buffer_r;
57
58 delegateWaveOutProc s_wave_callback;
59
60 /// コールバック関数
61 void wave_callback( IntPtr hwo, uint uMsg, uint dwInstance, uint dwParam1, uint dwParam2 ) {
62 #if DEBUG
63 Console.WriteLine( "WavePlay.wave_callback; uMsg=" + uMsg );
64 #endif
65 if ( uMsg == windows.MM_WOM_DONE ) {
66 int index_done = 0;
67 WAVEHDR whdr = (WAVEHDR)Marshal.PtrToStructure( new IntPtr( dwParam1 ), typeof( WAVEHDR ) );
68 int dwuser = whdr.dwUser.ToInt32();
69 if ( dwuser >= _NUM_BUF ) {
70 index_done = dwuser - _NUM_BUF;
71 } else {
72 index_done = dwuser;
73 }
74 #if DEBUG
75 bocoree.debug.push_log( "dwuser=" + dwuser );
76 bocoree.debug.push_log( "index_done=" + index_done );
77 #endif
78 s_done[index_done] = true;
79 if ( s_last_buffer == index_done ) {
80 s_playing = false;
81 }
82 if ( dwuser >= _NUM_BUF ) {
83 s_wave_header[index_done].dwUser = new IntPtr( index_done );
84 }
85 #if DEBUG
86 bocoree.debug.push_log( "whdr.dwUser=" + whdr.dwUser.ToInt32() );
87 bocoree.debug.push_log( "dwParam1=0x" + Convert.ToString( dwParam1, 16 ) + "; dwParam2=0x" + Convert.ToString( dwParam2, 16 ) );
88 #endif
89 }
90 }
91
92 void append_cor( float** a_data, uint length, double amp_left, double amp_right, bool is_last_mode ) {
93 #if DEBUG
94
95 bocoree.debug.push_log( "append_cor *************************************************************" );
96 bocoree.debug.push_log( " length=" + length );
97 bocoree.debug.push_log( " s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
98 #endif
99 s_playing = true;
100 int jmax = (int)length;
101 int remain = 0;
102 IntPtr ptr_data = IntPtr.Zero;
103 IntPtr ptr_data0 = IntPtr.Zero;
104 IntPtr ptr_data1 = IntPtr.Zero;
105 ptr_data = Marshal.AllocHGlobal( sizeof( float* ) * 2 );
106 float** data = (float**)ptr_data.ToPointer();// new float*[2];
107 bool cleaning_required = false;
108 if ( s_error_samples > 0 ) {
109 if ( s_error_samples >= length ) {
110 s_error_samples -= (int)length;
111 return;
112 }
113 cleaning_required = true;
114 int actual_length = (int)length - s_error_samples;
115 #if DEBUG
116 bocoree.debug.push_log( " actual_length=" + actual_length );
117 #endif
118 ptr_data0 = Marshal.AllocHGlobal( sizeof( float ) * actual_length );
119 ptr_data1 = Marshal.AllocHGlobal( sizeof( float ) * actual_length );
120 data[0] = (float*)ptr_data0.ToPointer();
121 data[1] = (float*)ptr_data1.ToPointer();
122 for ( int i = 0; i < actual_length; i++ ) {
123 data[0][i] = a_data[0][i + s_error_samples];
124 data[1][i] = a_data[1][i + s_error_samples];
125 }
126 s_error_samples = 0;
127 length = (uint)actual_length;
128 jmax = (int)length;
129 } else {
130 data = a_data;
131 }
132
133 if ( length + s_buffer_loc >= s_block_size ) {
134 jmax = s_block_size - s_buffer_loc;
135 remain = (int)length - (int)jmax;
136 }
137 float aright = (float)amp_right;
138 float aleft = (float)amp_left;
139
140 for ( int j = 0; j < jmax; j++ ) {
141 s_wave_buffer_l[j + s_buffer_loc] = data[1][j];
142 s_wave_buffer_r[j + s_buffer_loc] = data[0][j];
143 }
144 s_buffer_loc += jmax;
145
146 if ( s_buffer_loc >= s_block_size ) {
147 // バッファー充填完了.バッファーを転送し、waveOutWriteが書き込めるタイミングまで待機
148 #if DEBUG
149 bocoree.debug.push_log( "append_cor; waiting(1) " + s_current_buffer + "..." );
150 #endif
151 while ( true ) {
152 if ( s_abort_required ) {
153 s_abort_required = false;
154 goto clean_and_exit;
155 }
156 if ( s_done[s_current_buffer] ) {
157 break;
158 }
159 }
160 #if DEBUG
161 bocoree.debug.push_log( "append_cor; ...exit" );
162 #endif
163
164 s_processed_count++;
165 mix( (int)s_processed_count, aleft, aright );
166
167 if ( s_processed_count == _NUM_BUF ) {
168 s_done[0] = false;
169 #if DEBUG
170 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
171 #endif
172 uint ret = windows.waveOutWrite( s_hwave_out, ref s_wave_header[0], (uint)sizeof( WAVEHDR ) );
173 #if DEBUG
174 bocoree.debug.push_log( "...done; ret=" + ret );
175 #endif
176 #if DEBUG
177 bocoree.debug.push_log( "(s_first_buffer_wirtten_callback==null)=" + (s_first_buffer_written_callback == null) );
178 #endif
179 if ( s_first_buffer_written_callback != null ) {
180 #if DEBUG
181 bocoree.debug.push_log( "append_cor; calling s_first_buffer_written_callback" );
182 #endif
183 s_first_buffer_written_callback();
184 }
185 for ( int buffer_index = 1; buffer_index < _NUM_BUF; buffer_index++ ) {
186 s_done[buffer_index] = false;
187 #if DEBUG
188 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
189 #endif
190 uint ret2 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[buffer_index], (uint)sizeof( WAVEHDR ) );
191 #if DEBUG
192 bocoree.debug.push_log( "...done; ret2=" + ret2 );
193 #endif
194 }
195 s_current_buffer = _NUM_BUF - 1;
196 } else if ( s_processed_count > _NUM_BUF ) {
197 s_done[s_current_buffer] = false;
198 #if DEBUG
199 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
200 #endif
201 uint ret3 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[s_current_buffer], (uint)sizeof( WAVEHDR ) );
202 #if DEBUG
203 bocoree.debug.push_log( "...done; ret3=" + ret3 );
204 #endif
205 }
206 s_current_buffer++;
207 if ( s_current_buffer >= _NUM_BUF ) {
208 s_current_buffer = 0;
209 }
210
211 s_buffer_loc = 0;
212 }
213
214 if ( remain > 0 ) {
215 for ( int j = jmax; j < length; j++ ) {
216 s_wave_buffer_l[j - jmax] = data[1][j];
217 s_wave_buffer_r[j - jmax] = data[0][j];
218 }
219 if ( is_last_mode ) {
220 for ( int j = (int)length - jmax; j < s_block_size; j++ ) {
221 s_wave_buffer_l[j] = 0.0f;
222 s_wave_buffer_r[j] = 0.0f;
223 }
224 }
225 s_buffer_loc = remain;
226 }
227
228 if ( is_last_mode ) {
229 if ( s_processed_count < _NUM_BUF ) {
230 // _NUM_BUFブロック分のデータを未だ全て受信していない場合。バッファが未だひとつも書き込まれていないので
231 // 0番のブロックから順に書き込む
232 s_processed_count++;
233 mix( (int)s_processed_count, aleft, aright );
234 s_done[0] = false;
235 #if DEBUG
236 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
237 #endif
238 uint ret35 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[0], (uint)sizeof( WAVEHDR ) );
239 #if DEBUG
240 bocoree.debug.push_log( "...done; ret35=" + ret35 );
241 bocoree.debug.push_log( "(s_first_buffer_written_callback==null)=" + (s_first_buffer_written_callback == null) );
242 #endif
243 if ( s_first_buffer_written_callback != null ) {
244 #if DEBUG
245 bocoree.debug.push_log( "append_cor; calling s_first_buffer_written_callback" );
246 #endif
247 s_first_buffer_written_callback();
248 }
249 for ( int i = 1; i < _NUM_BUF - 1; i++ ) {
250 s_processed_count++;
251 mix( (int)s_processed_count, aleft, aright );
252 s_done[i] = false;
253 #if DEBUG
254 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
255 #endif
256 uint ret36 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[i], (uint)sizeof( WAVEHDR ) );
257 #if DEBUG
258 bocoree.debug.push_log( "...done; ret36=" + ret36 );
259 #endif
260 }
261 }
262 ulong zero = MAKELONG( 0, 0 );
263 for ( int j = s_buffer_loc; j < s_block_size; j++ ) {
264 s_wave_buffer_l[j] = 0.0f;
265 s_wave_buffer_r[j] = 0.0f;
266 }
267 #if DEBUG
268 bocoree.debug.push_log( "append_cor; waiting(3) " + s_current_buffer + "..." );
269 #endif
270 while ( !s_done[s_current_buffer] ) {
271 if ( s_abort_required ) {
272 s_abort_required = false;
273 goto clean_and_exit;
274 }
275 }
276 #if DEBUG
277 bocoree.debug.push_log( "append_cor; ...exit" );
278 #endif
279 s_processed_count++;
280 mix( (int)s_processed_count, aleft, aright );
281 s_done[s_current_buffer] = false;
282 #if DEBUG
283 bocoree.debug.push_log( "calling waveOutWrite...; s_hawve_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
284 #endif
285 uint ret4 = windows.waveOutWrite( s_hwave_out, ref s_wave_header[s_current_buffer], (uint)sizeof( WAVEHDR ) );
286 #if DEBUG
287 bocoree.debug.push_log( "...done; ret4=" + ret4 );
288 #endif
289 }
290 clean_and_exit:
291 if ( is_last_mode ) {
292 s_last_buffer = s_current_buffer;
293 }
294 if ( cleaning_required ) {
295 Marshal.FreeHGlobal( ptr_data0 ); //delete [] data[0];
296 Marshal.FreeHGlobal( ptr_data1 ); //delete [] data[1];
297 Marshal.FreeHGlobal( ptr_data ); //delete [] data;
298 }
299 }
300
301 void mix( int processed_count, float amp_left, float amp_right ) {
302 int current_buffer = (processed_count - 1) % _NUM_BUF;
303 for ( int k = 0; k < s_num_wave_reader; k++ ) {
304 s_wave_reader[k].Read( s_block_size * (processed_count - 1) + (int)s_wave_read_offset_samples,
305 s_block_size,
306 out s_ptr_another_wave_l[k],
307 out s_ptr_another_wave_r[k] );
308 }
309 for ( int i = 0; i < s_block_size; i++ ) {
310 float l = s_wave_buffer_l[i] * amp_left;
311 float r = s_wave_buffer_r[i] * amp_right;
312 for ( int k = 0; k < s_num_wave_reader; k++ ) {
313 l += s_another_wave_l[k][i];
314 r += s_another_wave_r[k][i];
315 }
316 s_wave[current_buffer][i] = MAKELONG( (ushort)(r * 32768.0f), (ushort)(l * 32768.0f) );
317 }
318 }
319
320 string util_get_errmsg( uint msg ) {
321 //IntPtr ptr_err = Marshal.AllocHGlobal( sizeof( byte ) * 260 );
322 //byte* err = (byte*)ptr_err.ToPointer();
323 //System.Text.StringBuilder sb = new System.Text.StringBuilder( 260 );
324 string ret = "";
325 windows.mciGetErrorStringA( msg, ret, 260 );
326 /*int len = 260;
327 for ( int i = 1; i < 260; i++ ) {
328 if ( err[i] == '\0' ) {
329 len = i - 1;
330 break;
331 }
332 }*/
333 //string ret = new string( err );
334 //string ret = sb.ToString();
335 //Marshal.FreeHGlobal( ptr_err );
336 return ret;
337 }
338
339 private WavePlay() {
340 }
341
342 /// 初期化関数
343 public WavePlay( int block_size, int sample_rate ) {
344 #if DEBUG
345 Console.WriteLine( "waveplay..ctor" );
346 #endif
347 s_block_size = block_size;
348 s_sample_rate = sample_rate;
349
350 //s_ptr_wave_formatx = Marshal.AllocHGlobal( sizeof( WAVEFORMATEX ) );
351 s_wave_formatx = new WAVEFORMATEX();
352 //Marshal.PtrToStructure( s_ptr_wave_formatx, s_wave_formatx );
353 s_wave_formatx.cbSize = (ushort)sizeof( WAVEFORMATEX );
354 #if DEBUG
355 Console.WriteLine( " s_wave_fomratx.cbSize=" + s_wave_formatx.cbSize );
356 Console.WriteLine( " sizeof( WAVEHDR )=" + sizeof( WAVEHDR ) );
357 #endif
358 s_wave_formatx.wFormatTag = windows.WAVE_FORMAT_PCM;
359 s_wave_formatx.nChannels = 2;
360 s_wave_formatx.wBitsPerSample = 16;
361 s_wave_formatx.nBlockAlign = (ushort)(s_wave_formatx.nChannels * s_wave_formatx.wBitsPerSample / 8);
362 s_wave_formatx.nSamplesPerSec = (uint)s_sample_rate;
363 s_wave_formatx.nAvgBytesPerSec = s_wave_formatx.nSamplesPerSec * s_wave_formatx.nBlockAlign;
364
365 s_wave_callback = new delegateWaveOutProc( wave_callback );
366 s_hwave_out = IntPtr.Zero;
367 Console.WriteLine( " calling waveOutOpen..." );
368 uint ret = windows.waveOutOpen( ref s_hwave_out,
369 windows.WAVE_MAPPER,
370 ref s_wave_formatx,
371 s_wave_callback,
372 IntPtr.Zero,
373 (uint)windows.CALLBACK_FUNCTION );
374 Console.WriteLine( " ...done; ret=" + ret );
375 #if DEBUG
376 bocoree.debug.push_log( " s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
377 #endif
378
379 for ( int k = 0; k < _NUM_BUF; k++ ) {
380 s_ptr_wave[k] = Marshal.AllocHGlobal( sizeof( uint ) * s_block_size );
381 s_wave[k] = (uint*)s_ptr_wave[k];// = (ulong*)calloc( sizeof( ulong ), s_block_size );
382 s_ptr_wave_header[k] = Marshal.AllocHGlobal( sizeof( WAVEHDR ) );
383 s_wave_header[k] = (WAVEHDR)Marshal.PtrToStructure( s_ptr_wave_header[k], typeof( WAVEHDR ) );
384 s_wave_header[k].lpData = s_ptr_wave[k];
385 s_wave_header[k].dwBufferLength = (uint)(sizeof( uint ) * s_block_size);
386 s_wave_header[k].dwFlags = windows.WHDR_BEGINLOOP | windows.WHDR_ENDLOOP;
387 s_wave_header[k].dwLoops = 1;
388
389 #if DEBUG
390 Console.WriteLine( "calling waveOutPrepareHeader..." );
391 #endif
392 uint ret2 = windows.waveOutPrepareHeader( s_hwave_out, ref s_wave_header[k], (uint)sizeof( WAVEHDR ) );
393 #if DEBUG
394 Console.WriteLine( "...done; ret2=" + ret2 );
395 #endif
396 s_wave_header[k].dwUser = new IntPtr( k );
397 }
398 #if DEBUG
399 bocoree.debug.push_log( " exit waveplay..ctor; s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
400 #endif
401 }
402
403 /// 波形データをバッファに追加する。バッファが再生中などの理由で即座に書き込めない場合、バッファが書き込み可能となるまで待機させられる
404 public void append( float** data, uint length, double amp_left, double amp_right ) {
405 append_cor( data, length, amp_left, amp_right, false );
406 }
407
408 public void flush_and_exit( double amp_left, double amp_right ) {
409 append_cor( (float**)0, 0, amp_left, amp_right, true );
410 }
411
412 /// 再生中断を要求する
413 public void abort() {
414 s_abort_required = true;
415 reset();
416 for ( int k = 0; k < _NUM_BUF; k++ ) {
417 if ( s_ptr_wave[k] != IntPtr.Zero ) {
418 for ( int i = 0; i < s_block_size; i++ ) {
419 s_wave[k][i] = 0;
420 }
421 //memset( s_wave[k], 0, s_block_size * sizeof( ulong ) );
422 }
423 }
424 s_buffer_loc = 0;
425 s_current_buffer = 0;
426 s_processed_count = 0;
427 }
428
429 /// 現在の再生位置を取得する。再生中でない場合負の値となる。
430 public float get_play_time() {
431 #if DEBUG
432 bocoree.debug.push_log( "WavePlay.get_play_time" );
433 #endif
434 if ( s_playing ) {
435 MMTIME mmt = new MMTIME();
436 mmt.cb = (uint)sizeof( MMTIME );
437 mmt.wType = windows.TIME_MS;
438 uint ret = windows.waveOutGetPosition( s_hwave_out, ref mmt, (uint)sizeof( MMTIME ) );
439 #if DEBUG
440 bocoree.debug.push_log( " ret=" + ret );
441 #endif
442 float ms = 0.0f;
443 switch ( mmt.wType ) {
444 case windows.TIME_MS:
445 return mmt.ms * 0.001f;
446 case windows.TIME_SAMPLES:
447 return (float)mmt.sample / (float)s_wave_formatx.nSamplesPerSec;
448 case windows.TIME_BYTES:
449 return (float)mmt.cb / (float)s_wave_formatx.nAvgBytesPerSec;
450 default:
451 return -1.0f;
452 }
453 } else {
454 return -1.0f;
455 }
456 }
457
458 /// リセットする。abort関数でも呼び出される。
459 public void reset() {
460 s_playing = false;
461 if ( s_hwave_out.ToInt32() != 0 ) {
462 for ( int k = 0; k < _NUM_BUF; k++ ) {
463 s_wave_header[k].dwUser = new IntPtr( _NUM_BUF + k );
464 }
465 windows.waveOutReset( s_hwave_out );
466 uint zero = MAKELONG( 0, 0 );
467 for ( int k = 0; k < _NUM_BUF; k++ ) {
468 for ( int i = 0; i < s_block_size; i++ ) {
469 s_wave[k][i] = zero;
470 }
471 }
472 }
473 for ( int i = 0; i < s_num_wave_reader; i++ ) {
474 s_wave_reader[i].Close();
475 }
476 }
477
478 /// 再生のための準備を行う。この関数を呼び出した後は、バッファが再生開始されるまでget_play_timeの戻り値は0となる(負値にならない)。
479 /// 戻り値は、filesに指定されたファイルの内、最も再生時間の長いwaveファイルの、合計サンプル数
480 public int on_your_mark( string[] files, long wave_read_offset_samples ) {
481 #if DEBUG
482 bocoree.debug.push_log( "on_your_mark; s_hwave_out=0x" + Convert.ToString( s_hwave_out.ToInt32(), 16 ) );
483 #endif
484 int num_files = files.Length;
485 reset();
486 s_wave_read_offset_samples = wave_read_offset_samples;
487 for ( int k = 0; k < _NUM_BUF; k++ ) {
488 s_wave_header[k].dwUser = new IntPtr( k );
489 s_done[k] = true;
490 }
491 s_abort_required = false;
492 s_buffer_loc = 0;
493 s_current_buffer = 0;
494 s_processed_count = 0;
495 s_playing = true;
496 s_last_buffer = -1;
497
498 if ( (int)s_ptr_wave_buffer_l.ToPointer() == 0 ) {
499 s_ptr_wave_buffer_l = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );// s_wave_buffer_l = new float[s_block_size];
500 s_wave_buffer_l = (float*)s_ptr_wave_buffer_l.ToPointer();
501 }
502 if ( (int)s_ptr_wave_buffer_r.ToPointer() == 0 ) {
503 s_ptr_wave_buffer_r = Marshal.AllocHGlobal( sizeof( float ) * s_block_size ); //s_wave_buffer_r = new float[s_block_size];
504 s_wave_buffer_r = (float*)s_ptr_wave_buffer_r.ToPointer();
505 }
506
507 if ( s_wave_reader != null ) {
508 for ( int i = 0; i < s_num_wave_reader; i++ ) {
509 s_wave_reader[i].Close();
510 }
511 //delete [] s_wave_reader;
512 }
513 s_wave_reader = new WaveReader[num_files];
514
515 if ( s_another_wave_l != null ) {
516 for ( int i = 0; i < s_num_wave_reader; i++ ) {
517 Marshal.FreeHGlobal( s_ptr_another_wave_l[i] );// delete [] s_another_wave_l[i];
518 }
519 //delete [] s_another_wave_l;
520 }
521 if ( s_another_wave_r != null ) {
522 for ( int i = 0; i < s_num_wave_reader; i++ ) {
523 Marshal.FreeHGlobal( s_ptr_another_wave_r[i] ); //delete [] s_another_wave_r[i];
524 }
525 //delete [] s_another_wave_r;
526 }
527 s_another_wave_l = new float*[num_files];
528 s_another_wave_r = new float*[num_files];
529 int max_samples = 0;
530 for ( int i = 0; i < num_files; i++ ) {
531 // waveファイルヘッダを読込む
532 /*int len = files[i].Length;
533 wchar_t *name = new wchar_t[len + 1];
534 array<wchar_t> ^buf = files[i]->ToCharArray();
535 for( int k = 0; k < len; k++ ){
536 name[k] = buf[k];
537 }
538 name[len] = '\0';*/
539 s_wave_reader[i].Open( files[i] );
540 int samples = s_wave_reader[i].TotalSamples;
541 if ( samples > max_samples ) {
542 max_samples = samples;
543 }
544 //delete [] name;
545
546 // バッファを用意
547 s_ptr_another_wave_l[i] = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );
548 s_another_wave_l[i] = (float*)s_ptr_another_wave_l[i].ToPointer();
549 s_ptr_another_wave_r[i] = Marshal.AllocHGlobal( sizeof( float ) * s_block_size );
550 s_another_wave_r[i] = (float*)s_ptr_another_wave_r[i].ToPointer();
551 //s_another_wave_l[i] = new float[s_block_size];
552 //s_another_wave_r[i] = new float[s_block_size];
553 }
554 s_num_wave_reader = num_files;
555 return max_samples;
556 }
557
558 public void set_error_samples( int error_samples ) {
559 s_error_samples = error_samples;
560 }
561
562 /// コールバック関数を設定する
563 public void set_first_buffer_written_callback( FirstBufferWrittenCallback proc ) {
564 s_first_buffer_written_callback = proc;
565 }
566
567 public void terminate() {
568 if ( s_hwave_out.ToInt32() != 0 ) {
569 windows.waveOutReset( s_hwave_out );
570 #if DEBUG
571 bocoree.debug.push_log( "waveplay::terminate; waveOutReset" );
572 #endif
573 for ( int k = 0; k < _NUM_BUF; k++ ) {
574 windows.waveOutUnprepareHeader( s_hwave_out, ref s_wave_header[k], (uint)sizeof( WAVEHDR ) );
575 }
576 windows.waveOutClose( s_hwave_out );
577 }
578 for ( int i = 0; i < _NUM_BUF; i++ ) {
579 if ( s_ptr_wave[i].ToInt32() != 0 ) {
580 Marshal.FreeHGlobal( s_ptr_wave[i] ); //delete [] s_wave[i];
581 }
582 }
583 }
584
585 /// 現在再生中かどうかを取得する
586 public bool is_alive() {
587 return s_playing;
588 }
589
590 /// ブロックサイズを変更します
591 public bool change_block_size( int block_size ) {
592 if ( s_playing ) {
593 return false;
594 }
595 if ( block_size <= 0 ) {
596 return false;
597 }
598
599 for ( int k = 0; k < _NUM_BUF; k++ ) {
600 if ( s_ptr_wave[k].ToInt32() != 0 ) {
601 Marshal.FreeHGlobal( s_ptr_wave[k] );// delete [] s_wave[k];
602 }
603 s_ptr_wave[k] = Marshal.AllocHGlobal( sizeof( uint ) * block_size );
604 s_wave[k] = (uint*)s_ptr_wave[k].ToPointer();// calloc( sizeof( ulong ), block_size );
605 s_wave_header[k].lpData = s_ptr_wave[k];
606 s_wave_header[k].dwBufferLength = (uint)(sizeof( uint ) * block_size);
607 }
608
609 // s_wave_buffer_l, s_wave_buffer_rは、NULLならばon_your_markで初期化されるので、開放だけやっておけばOK
610 if ( s_ptr_wave_buffer_l.ToInt32() != 0 ) {
611 Marshal.FreeHGlobal( s_ptr_wave_buffer_l ); //delete [] s_wave_buffer_l;
612 }
613 if ( s_ptr_wave_buffer_r.ToInt32() != 0 ) {
614 Marshal.FreeHGlobal( s_ptr_wave_buffer_r ); //delete[] s_wave_buffer_r;
615 }
616 // s_another_wave_l, s_another_wave_rは、on_your_markで全自動で初期化されるので特に操作の必要なし
617 s_block_size = block_size;
618 return true;
619 }
620
621 uint MAKELONG( ushort a, ushort b ) {
622 return (uint)(a & 0xffff) | (uint)((b & 0xffff) << 16);
623 }
624 }
625
626 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26