public void begin(long length, WorkerState state) { mRunning = true; mTotalSamples = length; long remain = length; while (remain > 0 && !state.isCancelRequested()) { int amount = (remain > BUFLEN) ? BUFLEN : (int)remain; mWaveSender.pull(mBufferL, mBufferR, amount); mReceiver.push(mBufferL, mBufferR, amount); remain -= amount; mTotalAppend += amount; } mWaveSender.end(); mReceiver.end(); mRunning = false; }
private void doSynthesis(long to_sample, double[] left, double[] right, WorkerState state) { int buffer_length = left.Length; long remain = to_sample - position_; while (0 < remain && !state.isCancelRequested()) { int process = buffer_length < remain ? buffer_length : (int)remain; Array.Clear(left, 0, process); Array.Clear(right, 0, process); driver_.process(left, right, process); if (receiver_ != null) { receiver_.push(left, right, process); } remain -= process; position_ += process; state.reportProgress(position_); } }
public void testMethod(WorkerState receiver, Object argument) { int wait_ms = 10; int amount = ((int)argument) / wait_ms; int proc = 0; for (int i = 0; i < amount; i++) { // 中止処理後にreportCompleteを送ってはいけない if (receiver.isCancelRequested()) { sout.println("TestFormWorker#testMethod; cancel requested"); return; } receiver.reportProgress(proc); Thread.Sleep(wait_ms); proc += wait_ms; } receiver.reportComplete(); sout.println("TestFormWorker#testMethod; job done"); }
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { int size = mThreads.Count; for (int i = 0; i < size; i++) { BackgroundWorker w = mThreads[i]; if (w == null) { continue; } if (w == sender) { WorkerState state = mArguments[i].state; if (state.isCancelRequested() == false) { workerCompleted(i); } break; } } }
public void begin(long total_samples, WorkerState state) { var mDriver = getDriver(); #if DEBUG sout.println("AquesToneRenderingRunner#begin; (mDriver==null)=" + (mDriver == null)); String file = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "AquesToneWaveGenerator.txt"); log = new System.IO.StreamWriter(file); log.AutoFlush = true; #endif if (mDriver == null) { #if DEBUG log.WriteLine("mDriver==null"); log.Close(); #endif exitBegin(); state.reportComplete(); return; } #if DEBUG sout.println("AquesToneRenderingRunner#begin; mDriver.loaded=" + mDriver.loaded); #endif if (!mDriver.loaded) { #if DEBUG log.WriteLine("mDriver.loaded=" + mDriver.loaded); log.Close(); #endif exitBegin(); state.reportComplete(); return; } mRunning = true; //mAbortRequired = false; mTotalSamples = total_samples; #if DEBUG sout.println("AquesToneWaveGenerator#begin; mTotalSamples=" + mTotalSamples); log.WriteLine("mTotalSamples=" + mTotalSamples); log.WriteLine("mTrimRemain=" + mTrimRemain); #endif VsqTrack track = mVsq.Track.get(mTrack); int BUFLEN = mSampleRate / 10; double[] left = new double[BUFLEN]; double[] right = new double[BUFLEN]; long saProcessed = 0; int saRemain = 0; int lastClock = 0; // 最後に処理されたゲートタイム // 最初にダミーの音を鳴らす // (最初に入るノイズを回避するためと、前回途中で再生停止した場合に無音から始まるようにするため) mDriver.resetAllParameters(); mDriver.process(left, right, BUFLEN); MidiEvent f_noteon = new MidiEvent(); f_noteon.firstByte = 0x90; f_noteon.data = new int[] { 0x40, 0x40 }; f_noteon.clock = 0; mDriver.send(new MidiEvent[] { f_noteon }); mDriver.process(left, right, BUFLEN); MidiEvent f_noteoff = new MidiEvent(); f_noteoff.firstByte = 0x80; f_noteoff.data = new int[] { 0x40, 0x7F }; mDriver.send(new MidiEvent[] { f_noteoff }); for (int i = 0; i < 3; i++) { mDriver.process(left, right, BUFLEN); } #if DEBUG log.WriteLine("pre-process done"); log.WriteLine("-----------------------------------------------------"); VsqTrack vsq_track = mVsq.Track.get(mTrack); for (Iterator <VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext();) { VsqEvent item = itr.next(); log.WriteLine("c" + item.Clock + "; " + item.ID.LyricHandle.L0.Phrase); } #endif // レンダリング開始位置での、パラメータの値をセットしておく for (Iterator <VsqEvent> itr = track.getNoteEventIterator(); itr.hasNext();) { VsqEvent item = itr.next(); #if DEBUG sout.println("AquesToneWaveGenerator#begin; item.Clock=" + item.Clock); log.WriteLine("*********************************************************"); log.WriteLine("item.Clock=" + item.Clock); #endif long saNoteStart = (long)(mVsq.getSecFromClock(item.Clock) * mSampleRate); long saNoteEnd = (long)(mVsq.getSecFromClock(item.Clock + item.ID.getLength()) * mSampleRate); #if DEBUG log.WriteLine("saNoteStart=" + saNoteStart + "; saNoteEnd=" + saNoteEnd); #endif EventQueueSequence list = generateMidiEvent(mVsq, mTrack, lastClock, item.Clock + item.ID.getLength()); lastClock = item.Clock + item.ID.Length + 1; for (Iterator <Integer> itr2 = list.keyIterator(); itr2.hasNext();) { // まず直前までの分を合成 Integer clock = itr2.next(); #if DEBUG log.WriteLine("-------------------------------------------------------"); sout.println("AquesToneWaveGenerator#begin; clock=" + clock); #endif long saStart = (long)(mVsq.getSecFromClock(clock) * mSampleRate); saRemain = (int)(saStart - saProcessed); #if DEBUG log.WriteLine("saStart=" + saStart); log.WriteLine("saRemain=" + saRemain); #endif while (saRemain > 0) { if (state.isCancelRequested()) { goto heaven; } int len = saRemain > BUFLEN ? BUFLEN : saRemain; mDriver.process(left, right, len); waveIncoming(left, right, len); saRemain -= len; saProcessed += len; state.reportProgress(saProcessed); //mTotalAppend += len; <- waveIncomingで計算されるので } // MIDiイベントを送信 MidiEventQueue queue = list.get(clock); // まずnoteoff boolean noteoff_send = false; if (queue.noteoff.size() > 0) { #if DEBUG for (int i = 0; i < queue.noteoff.size(); i++) { String str = ""; MidiEvent itemi = queue.noteoff.get(i); str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " "; for (int j = 0; j < itemi.data.Length; j++) { str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " "; } sout.println(typeof(AquesToneWaveGenerator) + "#begin; noteoff; " + str); } #endif mDriver.send(queue.noteoff.toArray(new MidiEvent[] { })); noteoff_send = true; } // parameterの変更 if (queue.param.size() > 0) { for (Iterator <ParameterEvent> itr3 = queue.param.iterator(); itr3.hasNext();) { ParameterEvent pe = itr3.next(); #if DEBUG sout.println(typeof(AquesToneWaveGenerator) + "#begin; param; index=" + pe.index + "; value=" + pe.value); #endif mDriver.setParameter(pe.index, pe.value); } } // ついでnoteon if (queue.noteon.size() > 0) { // 同ゲートタイムにピッチベンドも指定されている場合、同時に送信しないと反映されないようだ! if (queue.pit.size() > 0) { queue.noteon.addAll(queue.pit); queue.pit.clear(); } #if DEBUG for (int i = 0; i < queue.noteon.size(); i++) { String str = ""; MidiEvent itemi = queue.noteon.get(i); str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " "; for (int j = 0; j < itemi.data.Length; j++) { str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " "; } sout.println(typeof(AquesToneWaveGenerator) + "#begin; noteon; " + str); } #endif mDriver.send(queue.noteon.toArray(new MidiEvent[] { })); } // PIT if (queue.pit.size() > 0 && !noteoff_send) { #if DEBUG for (int i = 0; i < queue.pit.size(); i++) { String str = ""; MidiEvent itemi = queue.pit.get(i); str += "0x" + PortUtil.toHexString(itemi.firstByte, 2) + " "; for (int j = 0; j < itemi.data.Length; j++) { str += "0x" + PortUtil.toHexString(itemi.data[j], 2) + " "; } sout.println(typeof(AquesToneWaveGenerator) + "#begin; pit; " + str); } #endif mDriver.send(queue.pit.toArray(new MidiEvent[] { })); } if (mDriver.getUi(mMainWindow) != null) { mDriver.getUi(mMainWindow).invalidateUi(); } } } // totalSamplesに足りなかったら、追加してレンダリング saRemain = (int)(mTotalSamples - mTotalAppend); #if DEBUG sout.println("AquesToneRenderingRunner#run; totalSamples=" + mTotalSamples + "; mTotalAppend=" + mTotalAppend + "; saRemain=" + saRemain); #endif while (saRemain > 0) { if (state.isCancelRequested()) { goto heaven; } int len = saRemain > BUFLEN ? BUFLEN : saRemain; mDriver.process(left, right, len); waveIncoming(left, right, len); saRemain -= len; saProcessed += len; state.reportProgress(saProcessed); //mTotalAppend += len; } heaven: #if DEBUG log.Close(); #endif exitBegin(); state.reportComplete(); }
public void begin( long total_samples, WorkerState state ) { var mDriver = getDriver(); #if DEBUG sout.println( "AquesToneRenderingRunner#begin; (mDriver==null)=" + (mDriver == null) ); String file = System.IO.Path.Combine( System.Windows.Forms.Application.StartupPath, "AquesToneWaveGenerator.txt" ); log = new System.IO.StreamWriter( file ); log.AutoFlush = true; #endif if ( mDriver == null ) { #if DEBUG log.WriteLine( "mDriver==null" ); log.Close(); #endif exitBegin(); state.reportComplete(); return; } #if DEBUG sout.println( "AquesToneRenderingRunner#begin; mDriver.loaded=" + mDriver.loaded ); #endif if ( !mDriver.loaded ) { #if DEBUG log.WriteLine( "mDriver.loaded=" + mDriver.loaded ); log.Close(); #endif exitBegin(); state.reportComplete(); return; } mRunning = true; //mAbortRequired = false; mTotalSamples = total_samples; #if DEBUG sout.println( "AquesToneWaveGenerator#begin; mTotalSamples=" + mTotalSamples ); log.WriteLine( "mTotalSamples=" + mTotalSamples ); log.WriteLine( "mTrimRemain=" + mTrimRemain ); #endif VsqTrack track = mVsq.Track.get( mTrack ); int BUFLEN = mSampleRate / 10; double[] left = new double[BUFLEN]; double[] right = new double[BUFLEN]; long saProcessed = 0; int saRemain = 0; int lastClock = 0; // 最後に処理されたゲートタイム // 最初にダミーの音を鳴らす // (最初に入るノイズを回避するためと、前回途中で再生停止した場合に無音から始まるようにするため) mDriver.resetAllParameters(); mDriver.process( left, right, BUFLEN ); MidiEvent f_noteon = new MidiEvent(); f_noteon.firstByte = 0x90; f_noteon.data = new int[] { 0x40, 0x40 }; f_noteon.clock = 0; mDriver.send( new MidiEvent[] { f_noteon } ); mDriver.process( left, right, BUFLEN ); MidiEvent f_noteoff = new MidiEvent(); f_noteoff.firstByte = 0x80; f_noteoff.data = new int[] { 0x40, 0x7F }; mDriver.send( new MidiEvent[] { f_noteoff } ); for ( int i = 0; i < 3; i++ ) { mDriver.process( left, right, BUFLEN ); } #if DEBUG log.WriteLine( "pre-process done" ); log.WriteLine( "-----------------------------------------------------" ); VsqTrack vsq_track = mVsq.Track.get( mTrack ); for ( Iterator<VsqEvent> itr = vsq_track.getNoteEventIterator(); itr.hasNext(); ) { VsqEvent item = itr.next(); log.WriteLine( "c" + item.Clock + "; " + item.ID.LyricHandle.L0.Phrase ); } #endif // レンダリング開始位置での、パラメータの値をセットしておく for ( Iterator<VsqEvent> itr = track.getNoteEventIterator(); itr.hasNext(); ) { VsqEvent item = itr.next(); #if DEBUG sout.println( "AquesToneWaveGenerator#begin; item.Clock=" + item.Clock ); log.WriteLine( "*********************************************************" ); log.WriteLine( "item.Clock=" + item.Clock ); #endif long saNoteStart = (long)(mVsq.getSecFromClock( item.Clock ) * mSampleRate); long saNoteEnd = (long)(mVsq.getSecFromClock( item.Clock + item.ID.getLength() ) * mSampleRate); #if DEBUG log.WriteLine( "saNoteStart=" + saNoteStart + "; saNoteEnd=" + saNoteEnd ); #endif EventQueueSequence list = generateMidiEvent( mVsq, mTrack, lastClock, item.Clock + item.ID.getLength() ); lastClock = item.Clock + item.ID.Length + 1; for ( Iterator<Integer> itr2 = list.keyIterator(); itr2.hasNext(); ) { // まず直前までの分を合成 Integer clock = itr2.next(); #if DEBUG log.WriteLine( "-------------------------------------------------------" ); sout.println( "AquesToneWaveGenerator#begin; clock=" + clock ); #endif long saStart = (long)(mVsq.getSecFromClock( clock ) * mSampleRate); saRemain = (int)(saStart - saProcessed); #if DEBUG log.WriteLine( "saStart=" + saStart ); log.WriteLine( "saRemain=" + saRemain ); #endif while ( saRemain > 0 ) { if ( state.isCancelRequested() ) { goto heaven; } int len = saRemain > BUFLEN ? BUFLEN : saRemain; mDriver.process( left, right, len ); waveIncoming( left, right, len ); saRemain -= len; saProcessed += len; state.reportProgress( saProcessed ); //mTotalAppend += len; <- waveIncomingで計算されるので } // MIDiイベントを送信 MidiEventQueue queue = list.get( clock ); // まずnoteoff boolean noteoff_send = false; if ( queue.noteoff.size() > 0 ) { #if DEBUG for ( int i = 0; i < queue.noteoff.size(); i++ ) { String str = ""; MidiEvent itemi = queue.noteoff.get( i ); str += "0x" + PortUtil.toHexString( itemi.firstByte, 2 ) + " "; for ( int j = 0; j < itemi.data.Length; j++ ) { str += "0x" + PortUtil.toHexString( itemi.data[j], 2 ) + " "; } sout.println( typeof( AquesToneWaveGenerator ) + "#begin; noteoff; " + str ); } #endif mDriver.send( queue.noteoff.toArray( new MidiEvent[] { } ) ); noteoff_send = true; } // parameterの変更 if ( queue.param.size() > 0 ) { for ( Iterator<ParameterEvent> itr3 = queue.param.iterator(); itr3.hasNext(); ) { ParameterEvent pe = itr3.next(); #if DEBUG sout.println( typeof( AquesToneWaveGenerator ) + "#begin; param; index=" + pe.index + "; value=" + pe.value ); #endif mDriver.setParameter( pe.index, pe.value ); } } // ついでnoteon if ( queue.noteon.size() > 0 ) { // 同ゲートタイムにピッチベンドも指定されている場合、同時に送信しないと反映されないようだ! if ( queue.pit.size() > 0 ) { queue.noteon.addAll( queue.pit ); queue.pit.clear(); } #if DEBUG for ( int i = 0; i < queue.noteon.size(); i++ ) { String str = ""; MidiEvent itemi = queue.noteon.get( i ); str += "0x" + PortUtil.toHexString( itemi.firstByte, 2 ) + " "; for ( int j = 0; j < itemi.data.Length; j++ ) { str += "0x" + PortUtil.toHexString( itemi.data[j], 2 ) + " "; } sout.println( typeof( AquesToneWaveGenerator ) + "#begin; noteon; " + str ); } #endif mDriver.send( queue.noteon.toArray( new MidiEvent[] { } ) ); } // PIT if ( queue.pit.size() > 0 && !noteoff_send ) { #if DEBUG for ( int i = 0; i < queue.pit.size(); i++ ) { String str = ""; MidiEvent itemi = queue.pit.get( i ); str += "0x" + PortUtil.toHexString( itemi.firstByte, 2 ) + " "; for ( int j = 0; j < itemi.data.Length; j++ ) { str += "0x" + PortUtil.toHexString( itemi.data[j], 2 ) + " "; } sout.println( typeof( AquesToneWaveGenerator ) + "#begin; pit; " + str ); } #endif mDriver.send( queue.pit.toArray( new MidiEvent[] { } ) ); } if ( mDriver.getUi( mMainWindow ) != null ) { mDriver.getUi( mMainWindow ).invalidateUi(); } } } // totalSamplesに足りなかったら、追加してレンダリング saRemain = (int)(mTotalSamples - mTotalAppend); #if DEBUG sout.println( "AquesToneRenderingRunner#run; totalSamples=" + mTotalSamples + "; mTotalAppend=" + mTotalAppend + "; saRemain=" + saRemain ); #endif while ( saRemain > 0 ) { if ( state.isCancelRequested() ) { goto heaven; } int len = saRemain > BUFLEN ? BUFLEN : saRemain; mDriver.process( left, right, len ); waveIncoming( left, right, len ); saRemain -= len; saProcessed += len; state.reportProgress( saProcessed ); //mTotalAppend += len; } heaven: #if DEBUG log.Close(); #endif exitBegin(); state.reportComplete(); }
/// <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); }
private void doSynthesis( long to_sample, double[] left, double[] right, WorkerState state ) { int buffer_length = left.Length; long remain = to_sample - position_; while ( 0 < remain && !state.isCancelRequested() ) { int process = buffer_length < remain ? buffer_length : (int)remain; Array.Clear( left, 0, process ); Array.Clear( right, 0, process ); driver_.process( left, right, process ); if ( receiver_ != null ) { receiver_.push( left, right, process ); } remain -= process; position_ += process; state.reportProgress( position_ ); } }
/// <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; }