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");
        }
Beispiel #4
0
        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();
        }
Beispiel #7
0
        /// <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_ );
     }
 }
Beispiel #9
0
        /// <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;
        }