Пример #1
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);
        }
Пример #2
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;
        }