/// <summary> /// /// </summary> /// <param name="total_samples"></param> /// <param name="mode_infinite"></param> /// <param name="sample_rate"></param> /// <param name="runner">このドライバを駆動しているRenderingRunnerのオブジェクト</param> /// <returns></returns> public int startRendering(long total_samples, boolean mode_infinite, int sample_rate, IWaveIncoming runner, WorkerState state) { #if DEBUG sout.println("VocaloidDriver#startRendering; entry; total_samples=" + total_samples + "; sample_rate=" + sample_rate); #endif lock ( locker ) { rendering = true; //g_cancelRequired = false; g_progress = 0.0; sampleRate = sample_rate; Vector <MidiEvent> lpEvents = merge_events(s_track_events.get(0), s_track_events.get(1)); int current_count = -1; MidiEvent current = new MidiEvent();// = lpEvents; MemoryManager mman = null; float * left_ch; float * right_ch; float ** out_buffer; try { mman = new MemoryManager(); left_ch = (float *)mman.malloc(sizeof(float) * sampleRate).ToPointer(); right_ch = (float *)mman.malloc(sizeof(float) * sampleRate).ToPointer(); out_buffer = (float **)mman.malloc(sizeof(float *) * 2).ToPointer(); out_buffer[0] = left_ch; out_buffer[1] = right_ch; double[] buffer_l = new double[sampleRate]; double[] buffer_r = new double[sampleRate]; #if TEST org.kbinani.debug.push_log(" calling initial dispatch..."); #endif #if DEBUG sout.println("VocaloidDriver#startRendering; sampleRate=" + sampleRate); #endif aEffect.Dispatch(AEffectOpcodes.effSetSampleRate, 0, 0, IntPtr.Zero, (float)sampleRate); aEffect.Dispatch(AEffectOpcodes.effMainsChanged, 0, 1, IntPtr.Zero, 0); // ここではブロックサイズ=サンプリングレートということにする aEffect.Dispatch(AEffectOpcodes.effSetBlockSize, 0, sampleRate, IntPtr.Zero, 0); // レンダリングの途中で停止した場合,ここでProcessする部分が無音でない場合がある for (int i = 0; i < 3; i++) { aEffect.ProcessReplacing(IntPtr.Zero, new IntPtr(out_buffer), sampleRate); } #if TEST org.kbinani.debug.push_log(" ...done"); #endif int delay = 0; int duration = 0; int dwNow = 0; int dwPrev = 0; int dwDelta; int dwDelay = 0; int dwDeltaDelay = 0; int addr_msb = 0, addr_lsb = 0; int data_msb = 0, data_lsb = 0; int total_processed = 0; int total_processed2 = 0; #if TEST org.kbinani.debug.push_log(" getting dwDelay..."); #endif dwDelay = 0; Vector <MidiEvent> list = s_track_events.get(1); int list_size = list.size(); for (int i = 0; i < list_size; i++) { MidiEvent work = list.get(i); if ((work.firstByte & 0xf0) == 0xb0) { switch (work.data[0]) { case 0x63: addr_msb = work.data[1]; addr_lsb = 0; break; case 0x62: addr_lsb = work.data[1]; break; case 0x06: data_msb = work.data[1]; break; case 0x26: data_lsb = work.data[1]; if (addr_msb == 0x50 && addr_lsb == 0x01) { dwDelay = (data_msb & 0xff) << 7 | (data_lsb & 0x7f); } break; } } if (dwDelay > 0) { break; } } #if TEST org.kbinani.debug.push_log(" ...done; dwDelay=" + dwDelay); #endif while (!state.isCancelRequested()) { int process_event_count = current_count; int nEvents = 0; #if TEST org.kbinani.debug.push_log("lpEvents.Count=" + lpEvents.size()); #endif if (current_count < 0) { current_count = 0; current = lpEvents.get(current_count); process_event_count = current_count; } while (current.clock == dwNow) { // durationを取得 if ((current.firstByte & 0xf0) == 0xb0) { switch (current.data[0]) { case 0x63: addr_msb = current.data[1]; addr_lsb = 0; break; case 0x62: addr_lsb = current.data[1]; break; case 0x06: data_msb = current.data[1]; break; case 0x26: data_lsb = current.data[1]; // Note Duration in millisec if (addr_msb == 0x50 && addr_lsb == 0x4) { duration = data_msb << 7 | data_lsb; } break; } } nEvents++; if (current_count + 1 < lpEvents.size()) { current_count++; current = lpEvents.get(current_count); } else { break; } } if (current_count + 1 >= lpEvents.size()) { break; } double msNow = msec_from_clock(dwNow); dwDelta = (int)(msNow / 1000.0 * sampleRate) - total_processed; #if TEST org.kbinani.debug.push_log("dwNow=" + dwNow); org.kbinani.debug.push_log("dwPrev=" + dwPrev); org.kbinani.debug.push_log("dwDelta=" + dwDelta); #endif VstEvents *pVSTEvents = (VstEvents *)mman.malloc(sizeof(VstEvent) + nEvents * sizeof(VstEvent *)).ToPointer(); pVSTEvents->numEvents = 0; pVSTEvents->reserved = (VstIntPtr)0; for (int i = 0; i < nEvents; i++) { MidiEvent pProcessEvent = lpEvents.get(process_event_count); int event_code = pProcessEvent.firstByte; VstEvent * pVSTEvent = (VstEvent *)0; VstMidiEvent *pMidiEvent; switch (event_code) { case 0xf0: case 0xf7: case 0xff: break; default: pMidiEvent = (VstMidiEvent *)mman.malloc((int)(sizeof(VstMidiEvent) + (pProcessEvent.data.Length + 1) * sizeof(byte))).ToPointer(); pMidiEvent->byteSize = sizeof(VstMidiEvent); pMidiEvent->deltaFrames = dwDelta; pMidiEvent->detune = 0; pMidiEvent->flags = 1; pMidiEvent->noteLength = 0; pMidiEvent->noteOffset = 0; pMidiEvent->noteOffVelocity = 0; pMidiEvent->reserved1 = 0; pMidiEvent->reserved2 = 0; pMidiEvent->type = VstEventTypes.kVstMidiType; pMidiEvent->midiData[0] = (byte)(0xff & pProcessEvent.firstByte); for (int j = 0; j < pProcessEvent.data.Length; j++) { pMidiEvent->midiData[j + 1] = (byte)(0xff & pProcessEvent.data[j]); } pVSTEvents->events[pVSTEvents->numEvents++] = (int)(VstEvent *)pMidiEvent; break; } process_event_count++; //pProcessEvent = lpEvents[process_event_count]; } #if TEST org.kbinani.debug.push_log("calling Dispatch with effProcessEvents..."); #endif aEffect.Dispatch(AEffectXOpcodes.effProcessEvents, 0, 0, new IntPtr(pVSTEvents), 0); #if TEST org.kbinani.debug.push_log("...done"); #endif while (dwDelta > 0 && !state.isCancelRequested()) { int dwFrames = dwDelta > sampleRate ? sampleRate : dwDelta; #if TEST org.kbinani.debug.push_log("calling ProcessReplacing..."); #endif aEffect.ProcessReplacing(IntPtr.Zero, new IntPtr(out_buffer), dwFrames); #if TEST org.kbinani.debug.push_log("...done"); #endif int iOffset = dwDelay - dwDeltaDelay; if (iOffset > (int)dwFrames) { iOffset = (int)dwFrames; } if (iOffset == 0) { for (int i = 0; i < (int)dwFrames; i++) { buffer_l[i] = out_buffer[0][i]; buffer_r[i] = out_buffer[1][i]; } total_processed2 += dwFrames; runner.waveIncomingImpl(buffer_l, buffer_r, dwFrames, state); } else { dwDeltaDelay += iOffset; } dwDelta -= dwFrames; total_processed += dwFrames; } dwPrev = dwNow; dwNow = (int)current.clock; g_progress = total_processed / (double)total_samples * 100.0; } double msLast = msec_from_clock(dwNow); dwDelta = (int)(sampleRate * ((double)duration + (double)delay) / 1000.0 + dwDeltaDelay); if (total_samples - total_processed2 > dwDelta) { dwDelta = (int)total_samples - total_processed2; } while (dwDelta > 0 && !state.isCancelRequested()) { int dwFrames = dwDelta > sampleRate ? sampleRate : dwDelta; #if TEST org.kbinani.debug.push_log("calling ProcessReplacing..."); #endif aEffect.ProcessReplacing(IntPtr.Zero, new IntPtr(out_buffer), dwFrames); #if TEST org.kbinani.debug.push_log("...done"); #endif for (int i = 0; i < (int)dwFrames; i++) { buffer_l[i] = out_buffer[0][i]; buffer_r[i] = out_buffer[1][i]; } total_processed2 += dwFrames; runner.waveIncomingImpl(buffer_l, buffer_r, dwFrames, state); dwDelta -= dwFrames; total_processed += dwFrames; } #if TEST sout.println("vstidrv::StartRendering; total_processed=" + total_processed); #endif if (mode_infinite) { for (int i = 0; i < sampleRate; i++) { buffer_l[i] = 0.0; buffer_r[i] = 0.0; } while (!state.isCancelRequested()) { total_processed2 += sampleRate; runner.waveIncomingImpl(buffer_l, buffer_r, sampleRate, state); } } aEffect.Dispatch(AEffectOpcodes.effMainsChanged, 0, 0, IntPtr.Zero, 0); lpEvents.clear(); #if DEBUG sout.println("VocaloidDriver#startRendering; done; total_processed=" + total_processed + "; total_processed2=" + total_processed2); #endif } catch (Exception ex) { serr.println("VocaloidDriver#startRendering; ex=" + ex); } finally { if (mman != null) { try { mman.dispose(); } catch (Exception ex2) { serr.println("VocaloidDriver#startRendering; ex2=" + ex2); } } } rendering = false; g_saProcessed = 0; for (int i = 0; i < s_track_events.size(); i++) { s_track_events.get(i).clear(); } g_tempoList.clear(); //g_cancelRequired = false; } return(1); }
/// <summary> /// /// </summary> /// <param name="total_samples"></param> /// <param name="mode_infinite"></param> /// <param name="sample_rate"></param> /// <param name="runner">このドライバを駆動しているRenderingRunnerのオブジェクト</param> /// <returns></returns> public int startRendering( long total_samples, boolean mode_infinite, int sample_rate, IWaveIncoming runner, WorkerState state ) { #if DEBUG sout.println( "VocaloidDriver#startRendering; entry; total_samples=" + total_samples + "; sample_rate=" + sample_rate ); #endif lock ( locker ) { rendering = true; //g_cancelRequired = false; g_progress = 0.0; sampleRate = sample_rate; Vector<MidiEvent> lpEvents = merge_events( s_track_events.get( 0 ), s_track_events.get( 1 ) ); int current_count = -1; MidiEvent current = new MidiEvent();// = lpEvents; MemoryManager mman = null; float* left_ch; float* right_ch; float** out_buffer; try { mman = new MemoryManager(); left_ch = (float*)mman.malloc( sizeof( float ) * sampleRate ).ToPointer(); right_ch = (float*)mman.malloc( sizeof( float ) * sampleRate ).ToPointer(); out_buffer = (float**)mman.malloc( sizeof( float* ) * 2 ).ToPointer(); out_buffer[0] = left_ch; out_buffer[1] = right_ch; double[] buffer_l = new double[sampleRate]; double[] buffer_r = new double[sampleRate]; #if TEST org.kbinani.debug.push_log( " calling initial dispatch..." ); #endif #if DEBUG sout.println( "VocaloidDriver#startRendering; sampleRate=" + sampleRate ); #endif aEffect.Dispatch( AEffectOpcodes.effSetSampleRate, 0, 0, IntPtr.Zero, (float)sampleRate ); aEffect.Dispatch( AEffectOpcodes.effMainsChanged, 0, 1, IntPtr.Zero, 0 ); // ここではブロックサイズ=サンプリングレートということにする aEffect.Dispatch( AEffectOpcodes.effSetBlockSize, 0, sampleRate, IntPtr.Zero, 0 ); // レンダリングの途中で停止した場合,ここでProcessする部分が無音でない場合がある for ( int i = 0; i < 3; i++ ) { aEffect.ProcessReplacing( IntPtr.Zero, new IntPtr( out_buffer ), sampleRate ); } #if TEST org.kbinani.debug.push_log( " ...done" ); #endif int delay = 0; int duration = 0; int dwNow = 0; int dwPrev = 0; int dwDelta; int dwDelay = 0; int dwDeltaDelay = 0; int addr_msb = 0, addr_lsb = 0; int data_msb = 0, data_lsb = 0; int total_processed = 0; int total_processed2 = 0; #if TEST org.kbinani.debug.push_log( " getting dwDelay..." ); #endif dwDelay = 0; Vector<MidiEvent> list = s_track_events.get( 1 ); int list_size = list.size(); for ( int i = 0; i < list_size; i++ ) { MidiEvent work = list.get( i ); if ( (work.firstByte & 0xf0) == 0xb0 ) { switch ( work.data[0] ) { case 0x63: addr_msb = work.data[1]; addr_lsb = 0; break; case 0x62: addr_lsb = work.data[1]; break; case 0x06: data_msb = work.data[1]; break; case 0x26: data_lsb = work.data[1]; if ( addr_msb == 0x50 && addr_lsb == 0x01 ) { dwDelay = (data_msb & 0xff) << 7 | (data_lsb & 0x7f); } break; } } if ( dwDelay > 0 ) { break; } } #if TEST org.kbinani.debug.push_log( " ...done; dwDelay=" + dwDelay ); #endif while ( !state.isCancelRequested() ) { int process_event_count = current_count; int nEvents = 0; #if TEST org.kbinani.debug.push_log( "lpEvents.Count=" + lpEvents.size() ); #endif if ( current_count < 0 ) { current_count = 0; current = lpEvents.get( current_count ); process_event_count = current_count; } while ( current.clock == dwNow ) { // durationを取得 if ( (current.firstByte & 0xf0) == 0xb0 ) { switch ( current.data[0] ) { case 0x63: addr_msb = current.data[1]; addr_lsb = 0; break; case 0x62: addr_lsb = current.data[1]; break; case 0x06: data_msb = current.data[1]; break; case 0x26: data_lsb = current.data[1]; // Note Duration in millisec if ( addr_msb == 0x50 && addr_lsb == 0x4 ) { duration = data_msb << 7 | data_lsb; } break; } } nEvents++; if ( current_count + 1 < lpEvents.size() ) { current_count++; current = lpEvents.get( current_count ); } else { break; } } if ( current_count + 1 >= lpEvents.size() ) { break; } double msNow = msec_from_clock( dwNow ); dwDelta = (int)(msNow / 1000.0 * sampleRate) - total_processed; #if TEST org.kbinani.debug.push_log( "dwNow=" + dwNow ); org.kbinani.debug.push_log( "dwPrev=" + dwPrev ); org.kbinani.debug.push_log( "dwDelta=" + dwDelta ); #endif VstEvents* pVSTEvents = (VstEvents*)mman.malloc( sizeof( VstEvent ) + nEvents * sizeof( VstEvent* ) ).ToPointer(); pVSTEvents->numEvents = 0; pVSTEvents->reserved = (VstIntPtr)0; for ( int i = 0; i < nEvents; i++ ) { MidiEvent pProcessEvent = lpEvents.get( process_event_count ); int event_code = pProcessEvent.firstByte; VstEvent* pVSTEvent = (VstEvent*)0; VstMidiEvent* pMidiEvent; switch ( event_code ) { case 0xf0: case 0xf7: case 0xff: break; default: pMidiEvent = (VstMidiEvent*)mman.malloc( (int)(sizeof( VstMidiEvent ) + (pProcessEvent.data.Length + 1) * sizeof( byte )) ).ToPointer(); pMidiEvent->byteSize = sizeof( VstMidiEvent ); pMidiEvent->deltaFrames = dwDelta; pMidiEvent->detune = 0; pMidiEvent->flags = 1; pMidiEvent->noteLength = 0; pMidiEvent->noteOffset = 0; pMidiEvent->noteOffVelocity = 0; pMidiEvent->reserved1 = 0; pMidiEvent->reserved2 = 0; pMidiEvent->type = VstEventTypes.kVstMidiType; pMidiEvent->midiData[0] = (byte)(0xff & pProcessEvent.firstByte); for ( int j = 0; j < pProcessEvent.data.Length; j++ ) { pMidiEvent->midiData[j + 1] = (byte)(0xff & pProcessEvent.data[j]); } pVSTEvents->events[pVSTEvents->numEvents++] = (int)(VstEvent*)pMidiEvent; break; } process_event_count++; //pProcessEvent = lpEvents[process_event_count]; } #if TEST org.kbinani.debug.push_log( "calling Dispatch with effProcessEvents..." ); #endif aEffect.Dispatch( AEffectXOpcodes.effProcessEvents, 0, 0, new IntPtr( pVSTEvents ), 0 ); #if TEST org.kbinani.debug.push_log( "...done" ); #endif while ( dwDelta > 0 && !state.isCancelRequested() ) { int dwFrames = dwDelta > sampleRate ? sampleRate : dwDelta; #if TEST org.kbinani.debug.push_log( "calling ProcessReplacing..." ); #endif aEffect.ProcessReplacing( IntPtr.Zero, new IntPtr( out_buffer ), dwFrames ); #if TEST org.kbinani.debug.push_log( "...done" ); #endif int iOffset = dwDelay - dwDeltaDelay; if ( iOffset > (int)dwFrames ) { iOffset = (int)dwFrames; } if ( iOffset == 0 ) { for ( int i = 0; i < (int)dwFrames; i++ ) { buffer_l[i] = out_buffer[0][i]; buffer_r[i] = out_buffer[1][i]; } total_processed2 += dwFrames; runner.waveIncomingImpl( buffer_l, buffer_r, dwFrames, state ); } else { dwDeltaDelay += iOffset; } dwDelta -= dwFrames; total_processed += dwFrames; } dwPrev = dwNow; dwNow = (int)current.clock; g_progress = total_processed / (double)total_samples * 100.0; } double msLast = msec_from_clock( dwNow ); dwDelta = (int)(sampleRate * ((double)duration + (double)delay) / 1000.0 + dwDeltaDelay); if ( total_samples - total_processed2 > dwDelta ) { dwDelta = (int)total_samples - total_processed2; } while ( dwDelta > 0 && !state.isCancelRequested() ) { int dwFrames = dwDelta > sampleRate ? sampleRate : dwDelta; #if TEST org.kbinani.debug.push_log( "calling ProcessReplacing..." ); #endif aEffect.ProcessReplacing( IntPtr.Zero, new IntPtr( out_buffer ), dwFrames ); #if TEST org.kbinani.debug.push_log( "...done" ); #endif for ( int i = 0; i < (int)dwFrames; i++ ) { buffer_l[i] = out_buffer[0][i]; buffer_r[i] = out_buffer[1][i]; } total_processed2 += dwFrames; runner.waveIncomingImpl( buffer_l, buffer_r, dwFrames, state ); dwDelta -= dwFrames; total_processed += dwFrames; } #if TEST sout.println( "vstidrv::StartRendering; total_processed=" + total_processed ); #endif if ( mode_infinite ) { for ( int i = 0; i < sampleRate; i++ ) { buffer_l[i] = 0.0; buffer_r[i] = 0.0; } while ( !state.isCancelRequested() ) { total_processed2 += sampleRate; runner.waveIncomingImpl( buffer_l, buffer_r, sampleRate, state ); } } aEffect.Dispatch( AEffectOpcodes.effMainsChanged, 0, 0, IntPtr.Zero, 0 ); lpEvents.clear(); #if DEBUG sout.println( "VocaloidDriver#startRendering; done; total_processed=" + total_processed + "; total_processed2=" + total_processed2 ); #endif } catch ( Exception ex ) { serr.println( "VocaloidDriver#startRendering; ex=" + ex ); } finally { if ( mman != null ) { try { mman.dispose(); } catch ( Exception ex2 ) { serr.println( "VocaloidDriver#startRendering; ex2=" + ex2 ); } } } rendering = false; g_saProcessed = 0; for ( int i = 0; i < s_track_events.size(); i++ ) { s_track_events.get( i ).clear(); } g_tempoList.clear(); //g_cancelRequired = false; } return 1; }