Exemplo n.º 1
0
void waveLogWrite()
{
    // log to the file
    if (soundLogStart && pBurnSoundOut != NULL) {
        wave_write(pBurnSoundOut, nBurnSoundLen << 1);
        pBurnSoundOut = NULL;
    }
}
Exemplo n.º 2
0
static adv_error sound_start(struct advance_record_context* context, const char* file, double frequency, int stereo)
{
	unsigned* f;

	if (context->state.sound_active_flag)
		return -1;

	/* adjust the frequency to match the MP3 standard */
	f = SOUND_FREQUENCY_MAP;
	while (*f) {
		double v = *f;
		v /= frequency;
		if (v > 1)
			v = 1 / v;
		v = 1 - v;
		if (v<SOUND_FREQUENCY_ERROR) {
			context->state.sound_frequency = *f;
			break;
		}
                 ++f;
	}
	if (!*f)
		context->state.sound_frequency = frequency;

	context->state.sound_stereo_flag = stereo;
	context->state.sound_sample_counter = 0;
	context->state.sound_sample_size = 2;
	if (stereo)
		context->state.sound_sample_size *= 2;
	context->state.sound_stopped_flag = 0;

	sncpy(context->state.sound_file_buffer, sizeof(context->state.sound_file_buffer), file);

	context->state.sound_f = fopen(context->state.sound_file_buffer, "wb");
	if (!context->state.sound_f) {
		log_std(("ERROR: opening file %s\n", context->state.sound_file_buffer));
		return -1;
	}

	if (wave_write(context->state.sound_f, context->state.sound_stereo_flag ? 2 : 1, 16, 0, context->state.sound_frequency) != 0) {
		log_std(("ERROR: writing file %s\n", context->state.sound_file_buffer));
		fclose(context->state.sound_f);
		remove(context->state.sound_file_buffer);
		return -1;
	}

	context->state.sound_active_flag = 1;

	return 0;
}
Exemplo n.º 3
0
void record_wav( const char* path, int secs )
{
	/* Start writing wave file */
	wave_open( spc_sample_rate, path );
	wave_enable_stereo();
	while ( wave_sample_count() < secs * spc_sample_rate * 2 )
	{
		/* Play into buffer */
		#define BUF_SIZE 2048
		short buf [BUF_SIZE];
		error( spc_play( snes_spc, BUF_SIZE, buf ) );
		
		wave_write( buf, BUF_SIZE );
	}
	wave_close();
}
Exemplo n.º 4
0
int main( int argc, char** argv )
{
	/* Create emulator and filter */
	SNES_SPC* snes_spc = spc_new();
	SPC_Filter* filter = spc_filter_new();
	if ( !snes_spc || !filter ) error( "Out of memory" );
	
	/* Load SPC */
	{
		/* Load file into memory */
		long spc_size;
		void* spc = load_file( (argc > 1) ? argv [1] : "test.spc", &spc_size );
		
		/* Load SPC data into emulator */
		error( spc_load_spc( snes_spc, spc, spc_size ) );
		free( spc ); /* emulator makes copy of data */
		
		/* Most SPC files have garbage data in the echo buffer, so clear that */
		spc_clear_echo( snes_spc );
		
		/* Clear filter before playing */
		spc_filter_clear( filter );
	}
	
	/* Record 20 seconds to wave file */
	wave_open( spc_sample_rate, "out.wav" );
	wave_enable_stereo();
	while ( wave_sample_count() < 60 * spc_sample_rate * 2 )
	{
		/* Play into buffer */
		#define BUF_SIZE 2048
		short buf [BUF_SIZE];
		error( spc_play( snes_spc, BUF_SIZE, buf ) );
		
		/* Filter samples */
		spc_filter_run( filter, buf, BUF_SIZE );
		
		wave_write( buf, BUF_SIZE );
	}
	
	/* Cleanup */
	spc_filter_delete( filter );
	spc_delete( snes_spc );
	wave_close();
	
	return 0;
}
Exemplo n.º 5
0
/**
 * NOT USED
 */
void
Java_com_example_subtle_SoundMachine_convertToWave( JNIEnv* env, jobject callingObject, jstring fromPath, jstring toPath )
{
	/* Buffer Size */
	int buf_size = 1024; /* can be any multiple of 2 */

	/* Grab Paths */
	const char *from_path = (*env)->GetStringUTFChars(env, fromPath, 0);
	const char *to_path = (*env)->GetStringUTFChars(env, toPath, 0);

	/* Open music file in new emulator */
	Music_Emu* emu;
	handle_error( gme_open_file( from_path, &emu, SAMPLE_RATE ) );

	/* Get Track Info */
	gme_info_t* track_info = NULL;
	handle_error( gme_track_info( emu, &track_info, TRACK ) );

	/* Start track */
	handle_error( gme_start_track( emu, TRACK ) );

	/* Begin writing to wave file */
	wave_open( SAMPLE_RATE, to_path );
	wave_enable_stereo();

	/* Output to Wave */
	while ( gme_tell( emu ) < track_info->play_length )
	{
		/* Sample buffer */
		short buf [buf_size];

		/* Fill sample buffer */
		handle_error( gme_play( emu, buf_size, buf ) );

		/* Write samples to wave file */
		wave_write( buf, buf_size );
	}

	/* Cleanup */
	gme_free_info( track_info );
	(*env)->ReleaseStringUTFChars(env, fromPath, from_path);
	(*env)->ReleaseStringUTFChars(env, toPath, to_path);
	gme_delete( emu );
	wave_close();
}
Exemplo n.º 6
0
Arquivo: basics.c Projeto: STJr/SRB2
int main(int argc, char *argv[])
{
	const char *filename = "test.nsf"; /* Default file to open */
	if ( argc >= 2 )
		filename = argv[1];

	long sample_rate = 44100; /* number of samples per second */
	/* index of track to play (0 = first) */
	int track = argc >= 3 ? atoi(argv[2]) : 0;
	
	/* Open music file in new emulator */
	Music_Emu* emu;
	handle_error( gme_open_file( filename, &emu, sample_rate ) );
	
	/* Start track */
	handle_error( gme_start_track( emu, track ) );
	
	/* Begin writing to wave file */
	wave_open( sample_rate, "out.wav" );
	wave_enable_stereo();
	
	/* Record 10 seconds of track */
	while ( gme_tell( emu ) < 10 * 1000L )
	{
		/* Sample buffer */
		#define buf_size 1024 /* can be any multiple of 2 */
		short buf [buf_size];
		
		/* Fill sample buffer */
		handle_error( gme_play( emu, buf_size, buf ) );
		
		/* Write samples to wave file */
		wave_write( buf, buf_size );
	}
	
	/* Cleanup */
	gme_delete( emu );
	wave_close();
	
	return 0;
}
Exemplo n.º 7
0
void wave_close(int id)
{
	struct wave_file *w = &wave[id];

    if( !w->file )
		return;

    if( w->timer )
	{
		if( w->channel != -1 )
			stream_update(w->channel, 0);
		w->samples = w->playpos;
		w->length = w->samples * w->resolution / 8;
		timer_remove(w->timer);
		w->timer = NULL;
	}

    if( w->mode )
	{
		wave_output(id,0);
		wave_write(id);
		w->mode = 0;
	}

    if( w->data )
		free(w->data);
    w->data = NULL;

	if (w->file) {
		osd_fclose(w->file);
		w->file = NULL;
	}
	w->offset = 0;
	w->playpos = 0;
	w->counter = 0;
	w->smpfreq = 0;
	w->resolution = 0;
	w->samples = 0;
	w->length = 0;
}
Exemplo n.º 8
0
int main(int argc, char **argv)
{
    std::fprintf(stdout, "==========================================\n"
                        #ifdef HARDWARE_OPL3
                         "      libADLMIDI demo utility (HW OPL)\n"
                        #else
                         "         libADLMIDI demo utility\n"
                        #endif
                         "==========================================\n\n");
    flushout(stdout);

    if(argc < 2 || std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h")
    {
        std::printf(
            "Usage: adlmidi <midifilename> [ <options> ] [ <bank> [ <numchips> [ <numfourops>] ] ]\n"
            " -p Enables adlib percussion instrument mode\n"
            " -t Enables tremolo amplification mode\n"
            " -v Enables vibrato amplification mode\n"
            " -s Enables scaling of modulator volumes\n"
            " -frb Enables full-ranged CC74 XG Brightness controller\n"
            " -nl Quit without looping\n"
            " -w Write WAV file rather than playing\n"
            " -mb Run the test of multibank over embedded. 62, 14, 68, and 74'th banks will be combined into one\n"
            " --solo <track>             Selects a solo track to play\n"
            " --only <track1,...,trackN> Selects a subset of tracks to play\n"
            #ifndef HARDWARE_OPL3
            " -fp Enables full-panning stereo support\n"
            " --emu-nuked  Uses Nuked OPL3 v 1.8 emulator\n"
            " --emu-nuked7 Uses Nuked OPL3 v 1.7.4 emulator\n"
            " --emu-dosbox Uses DosBox 0.74 OPL3 emulator\n"
            #endif
            "\n"
            "Where <bank> - number of embeeded bank or filepath to custom WOPL bank file\n"
            "\n"
            "Note: To create WOPL bank files use OPL Bank Editor you can get here: \n"
            "https://github.com/Wohlstand/OPL3BankEditor\n"
            "\n"
        );

        // Get count of embedded banks (no initialization needed)
        int banksCount = adl_getBanksCount();
        //Get pointer to list of embedded bank names
        const char *const *banknames = adl_getBankNames();

        if(banksCount > 0)
        {
            std::printf("    Available embedded banks by number:\n\n");

            for(int a = 0; a < banksCount; ++a)
                std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]);

            std::printf(
                "\n"
                "     Use banks 2-5 to play Descent \"q\" soundtracks.\n"
                "     Look up the relevant bank number from descent.sng.\n"
                "\n"
                "     The fourth parameter can be used to specify the number\n"
                "     of four-op channels to use. Each four-op channel eats\n"
                "     the room of two regular channels. Use as many as required.\n"
                "     The Doom & Hexen sets require one or two, while\n"
                "     Miles four-op set requires the maximum of numcards*6.\n"
                "\n"
            );
        }
        else
        {
            std::printf("    This build of libADLMIDI has no embedded banks!\n\n");
        }

        flushout(stdout);

        return 0;
    }

    long sampleRate = 44100;
    #ifndef HARDWARE_OPL3
    //const unsigned MaxSamplesAtTime = 512; // 512=dbopl limitation
    // How long is SDL buffer, in seconds?
    // The smaller the value, the more often SDL_AudioCallBack()
    // is called.
    const double AudioBufferLength = 0.08;
    // How much do WE buffer, in seconds? The smaller the value,
    // the more prone to sound chopping we are.
    const double OurHeadRoomLength = 0.1;
    // The lag between visual content and audio content equals
    // the sum of these two buffers.
    #ifndef OUTPUT_WAVE_ONLY
    SDL_AudioSpec spec;
    SDL_AudioSpec obtained;

    spec.freq     = (int)sampleRate;
    spec.format   = AUDIO_S16SYS;
    spec.channels = 2;
    spec.samples  = Uint16((double)spec.freq * AudioBufferLength);
    spec.callback = SDL_AudioCallbackX;
    #endif //OUTPUT_WAVE_ONLY
    #endif //HARDWARE_OPL3

    ADL_MIDIPlayer *myDevice;

    //Initialize libADLMIDI and create the instance (you can initialize multiple of them!)
    myDevice = adl_init(sampleRate);
    if(myDevice == NULL)
    {
        printError("Failed to init MIDI device!\n");
        return 1;
    }

    //Set internal debug messages hook to print all libADLMIDI's internal debug messages
    adl_setDebugMessageHook(myDevice, debugPrint, NULL);

    /*
     * Set library options by parsing of command line arguments
     */
    bool multibankFromEnbededTest = false;

#ifndef OUTPUT_WAVE_ONLY
    bool recordWave = false;
    int loopEnabled = 1;
#endif

#ifndef HARDWARE_OPL3
    int emulator = ADLMIDI_EMU_NUKED;
#endif

    size_t soloTrack = ~(size_t)0;
    std::vector<size_t> onlyTracks;

#if !defined(HARDWARE_OPL3) && !defined(OUTPUT_WAVE_ONLY)
    g_audioFormat.type = ADLMIDI_SampleType_S16;
    g_audioFormat.containerSize = sizeof(Sint16);
    g_audioFormat.sampleOffset = sizeof(Sint16) * 2;
#endif

    while(argc > 2)
    {
        bool had_option = false;

        if(!std::strcmp("-p", argv[2]))
            adl_setPercMode(myDevice, 1);//Turn on AdLib percussion mode
        else if(!std::strcmp("-v", argv[2]))
            adl_setHVibrato(myDevice, 1);//Force turn on deep vibrato

#if !defined(OUTPUT_WAVE_ONLY) && !defined(HARDWARE_OPL3)
        else if(!std::strcmp("-w", argv[2]))
        {
            //Current Wave output implementation allows only SINT16 output
            g_audioFormat.type = ADLMIDI_SampleType_S16;
            g_audioFormat.containerSize = sizeof(Sint16);
            g_audioFormat.sampleOffset = sizeof(Sint16) * 2;
            recordWave = true;//Record library output into WAV file
        }
        else if(!std::strcmp("-s8", argv[2]) && !recordWave)
            spec.format = AUDIO_S8;
        else if(!std::strcmp("-u8", argv[2]) && !recordWave)
            spec.format = AUDIO_U8;
        else if(!std::strcmp("-s16", argv[2]) && !recordWave)
            spec.format = AUDIO_S16;
        else if(!std::strcmp("-u16", argv[2]) && !recordWave)
            spec.format = AUDIO_U16;
        else if(!std::strcmp("-s32", argv[2]) && !recordWave)
            spec.format = AUDIO_S32;
        else if(!std::strcmp("-f32", argv[2]) && !recordWave)
            spec.format = AUDIO_F32;
#endif

        else if(!std::strcmp("-t", argv[2]))
            adl_setHTremolo(myDevice, 1);//Force turn on deep tremolo

        else if(!std::strcmp("-frb", argv[2]))
            adl_setFullRangeBrightness(myDevice, 1);//Turn on a full-ranged XG CC74 Brightness

#ifndef OUTPUT_WAVE_ONLY
        else if(!std::strcmp("-nl", argv[2]))
            loopEnabled = 0; //Enable loop
#endif

#ifndef HARDWARE_OPL3
        else if(!std::strcmp("--emu-nuked", argv[2]))
            emulator = ADLMIDI_EMU_NUKED;
        else if(!std::strcmp("--emu-nuked7", argv[2]))
            emulator = ADLMIDI_EMU_NUKED_174;
        else if(!std::strcmp("--emu-dosbox", argv[2]))
            emulator = ADLMIDI_EMU_DOSBOX;
#endif
        else if(!std::strcmp("-fp", argv[2]))
            adl_setSoftPanEnabled(myDevice, 1);
        else if(!std::strcmp("-mb", argv[2]))
            multibankFromEnbededTest = true;
        else if(!std::strcmp("-s", argv[2]))
            adl_setScaleModulators(myDevice, 1);//Turn on modulators scaling by volume

        else if(!std::strcmp("--solo", argv[2]))
        {
            if(argc <= 3)
            {
                printError("The option --solo requires an argument!\n");
                return 1;
            }
            soloTrack = std::strtoul(argv[3], NULL, 0);
            had_option = true;
        }
        else if(!std::strcmp("--only", argv[2]))
        {
            if(argc <= 3)
            {
                printError("The option --only requires an argument!\n");
                return 1;
            }

            const char *strp = argv[3];
            unsigned long value;
            unsigned size;
            bool err = std::sscanf(strp, "%lu%n", &value, &size) != 1;
            while(!err && *(strp += size))
            {
                onlyTracks.push_back(value);
                err = std::sscanf(strp, ",%lu%n", &value, &size) != 1;
            }
            if(err)
            {
                printError("Invalid argument to --only!\n");
                return 1;
            }
            onlyTracks.push_back(value);
            had_option = true;
        }

        else break;

        std::copy(argv + (had_option ? 4 : 3),
                  argv + argc,
                  argv + 2);
        argc -= (had_option ? 2 : 1);
    }

#ifndef OUTPUT_WAVE_ONLY
    //Turn loop on/off (for WAV recording loop must be disabled!)
    adl_setLoopEnabled(myDevice, recordWave ? 0 : loopEnabled);
#endif

#ifdef DEBUG_TRACE_ALL_EVENTS
    //Hook all MIDI events are ticking while generating an output buffer
    if(!recordWave)
        adl_setRawEventHook(myDevice, debugPrintEvent, NULL);
#endif

#ifndef HARDWARE_OPL3
    adl_switchEmulator(myDevice, emulator);
#endif

    std::fprintf(stdout, " - Library version %s\n", adl_linkedLibraryVersion());
#ifdef HARDWARE_OPL3
    std::fprintf(stdout, " - Hardware OPL3 chip in use\n");
#else
    std::fprintf(stdout, " - %s Emulator in use\n", adl_chipEmulatorName(myDevice));
#endif

#if !defined(HARDWARE_OPL3) && !defined(OUTPUT_WAVE_ONLY)
    if(!recordWave)
    {
        // Set up SDL
        if(SDL_OpenAudio(&spec, &obtained) < 0)
        {
            std::fprintf(stderr, "\nERROR: Couldn't open audio: %s\n\n", SDL_GetError());
            //return 1;
        }
        if(spec.samples != obtained.samples)
        {
            std::fprintf(stderr, " - Audio wanted (format=%s,samples=%u,rate=%u,channels=%u);\n"
                                 " - Audio obtained (format=%s,samples=%u,rate=%u,channels=%u)\n",
                         SDLAudioToStr(spec.format), spec.samples,    spec.freq,    spec.channels,
                         SDLAudioToStr(obtained.format), obtained.samples, obtained.freq, obtained.channels);
        }
        switch(obtained.format)
        {
        case AUDIO_S8:
            g_audioFormat.type = ADLMIDI_SampleType_S8;
            g_audioFormat.containerSize = sizeof(Sint8);
            g_audioFormat.sampleOffset = sizeof(Sint8) * 2;
            break;
        case AUDIO_U8:
            g_audioFormat.type = ADLMIDI_SampleType_U8;
            g_audioFormat.containerSize = sizeof(Uint8);
            g_audioFormat.sampleOffset = sizeof(Uint8) * 2;
            break;
        case AUDIO_S16:
            g_audioFormat.type = ADLMIDI_SampleType_S16;
            g_audioFormat.containerSize = sizeof(Sint16);
            g_audioFormat.sampleOffset = sizeof(Sint16) * 2;
            break;
        case AUDIO_U16:
            g_audioFormat.type = ADLMIDI_SampleType_U16;
            g_audioFormat.containerSize = sizeof(Uint16);
            g_audioFormat.sampleOffset = sizeof(Uint16) * 2;
            break;
        case AUDIO_S32:
            g_audioFormat.type = ADLMIDI_SampleType_S32;
            g_audioFormat.containerSize = sizeof(Sint32);
            g_audioFormat.sampleOffset = sizeof(Sint32) * 2;
            break;
        case AUDIO_F32:
            g_audioFormat.type = ADLMIDI_SampleType_F32;
            g_audioFormat.containerSize = sizeof(float);
            g_audioFormat.sampleOffset = sizeof(float) * 2;
            break;
        }
    }
#endif

    if(argc >= 3)
    {
        if(is_number(argv[2]))
        {
            int bankno = std::atoi(argv[2]);
            //Choose one of embedded banks
            if(adl_setBank(myDevice, bankno) != 0)
            {
                printError(adl_errorInfo(myDevice));
                return 1;
            }
            std::fprintf(stdout, " - Use embedded bank #%d [%s]\n", bankno, adl_getBankNames()[bankno]);
        }
        else
        {
            std::string bankPath = argv[2];
            std::fprintf(stdout, " - Use custom bank [%s]...", bankPath.c_str());
            flushout(stdout);
            //Open external bank file (WOPL format is supported)
            //to create or edit them, use OPL3 Bank Editor you can take here https://github.com/Wohlstand/OPL3BankEditor
            if(adl_openBankFile(myDevice, bankPath.c_str()) != 0)
            {
                std::fprintf(stdout, "FAILED!\n");
                flushout(stdout);
                printError(adl_errorInfo(myDevice));
                return 1;
            }
            std::fprintf(stdout, "OK!\n");
        }
    }

    if(multibankFromEnbededTest)
    {
        ADL_BankId id[] =
        {
            {0, 0, 0}, /*62*/ // isPercussion, MIDI bank MSB, LSB
            {0, 8, 0}, /*14*/ // Use as MSB-8
            {1, 0, 0}, /*68*/
            {1, 0, 25} /*74*/
        };
        int banks[] =
        {
            62, 14, 68, 74
        };

        for(size_t i = 0; i < 4; i++)
        {
            ADL_Bank bank;
            if(adl_getBank(myDevice, &id[i], ADLMIDI_Bank_Create, &bank) < 0)
            {
                printError(adl_errorInfo(myDevice));
                return 1;
            }

            if(adl_loadEmbeddedBank(myDevice, &bank, banks[i]) < 0)
            {
                printError(adl_errorInfo(myDevice));
                return 1;
            }
        }

        std::fprintf(stdout, " - Ran a test of multibank over embedded\n");
    }

#ifndef HARDWARE_OPL3
    int numOfChips = 4;
    if(argc >= 4)
        numOfChips = std::atoi(argv[3]);

    //Set count of concurrent emulated chips count to excite channels limit of one chip
    if(adl_setNumChips(myDevice, numOfChips) != 0)
    {
        printError(adl_errorInfo(myDevice));
        return 1;
    }
    std::fprintf(stdout, " - Number of chips %d\n", adl_getNumChips(myDevice));
#else
    int numOfChips = 1;
    adl_setNumChips(myDevice, numOfChips);
#endif

    if(argc >= 5)
    {
        //Set total count of 4-operator channels between all emulated chips
        if(adl_setNumFourOpsChn(myDevice, std::atoi(argv[4])) != 0)
        {
            printError(adl_errorInfo(myDevice));
            return 1;
        }
    }
    std::fprintf(stdout, " - Number of four-ops %d\n", adl_getNumFourOpsChn(myDevice));

    std::string musPath = argv[1];
    //Open MIDI file to play
    if(adl_openFile(myDevice, musPath.c_str()) != 0)
    {
        printError(adl_errorInfo(myDevice));
        return 2;
    }

    std::fprintf(stdout, " - Track count: %lu\n", (unsigned long)adl_trackCount(myDevice));

    if(soloTrack != ~(size_t)0)
    {
        std::fprintf(stdout, " - Solo track: %lu\n", (unsigned long)soloTrack);
        adl_setTrackOptions(myDevice, soloTrack, ADLMIDI_TrackOption_Solo);
    }

    if(!onlyTracks.empty())
    {
        size_t count = adl_trackCount(myDevice);
        for(size_t track = 0; track < count; ++track)
            adl_setTrackOptions(myDevice, track, ADLMIDI_TrackOption_Off);
        std::fprintf(stdout, " - Only tracks:");
        for(size_t i = 0, n = onlyTracks.size(); i < n; ++i)
        {
            size_t track = onlyTracks[i];
            adl_setTrackOptions(myDevice, track, ADLMIDI_TrackOption_On);
            std::fprintf(stdout, " %lu", (unsigned long)track);
        }
        std::fprintf(stdout, "\n");
    }

    std::fprintf(stdout, " - File [%s] opened!\n", musPath.c_str());
    flushout(stdout);

#ifndef HARDWARE_OPL3
    signal(SIGINT, sighandler);
    signal(SIGTERM, sighandler);
#   if !defined(_WIN32) && !defined(__WATCOMC__)
    signal(SIGHUP, sighandler);
#   endif

#else//HARDWARE_OPL3
    static const unsigned NewTimerFreq = 209;
    unsigned TimerPeriod = 0x1234DDul / NewTimerFreq;

    #ifdef __DJGPP__
    //disable();
    outportb(0x43, 0x34);
    outportb(0x40, TimerPeriod & 0xFF);
    outportb(0x40, TimerPeriod >>   8);
    //enable();
    #endif//__DJGPP__

    #ifdef __WATCOMC__
    std::fprintf(stdout, " - Initializing BIOS timer...\n");
    flushout(stdout);
    //disable();
    outp(0x43, 0x34);
    outp(0x40, TimerPeriod & 0xFF);
    outp(0x40, TimerPeriod >>   8);
    //enable();
    std::fprintf(stdout, " - Ok!\n");
    flushout(stdout);
    #endif//__WATCOMC__

    unsigned long BIOStimer_begin = BIOStimer;
    double tick_delay = 0.0;
#endif//HARDWARE_OPL3

    double total        = adl_totalTimeLength(myDevice);

#ifndef OUTPUT_WAVE_ONLY
    double loopStart    = adl_loopStartTime(myDevice);
    double loopEnd      = adl_loopEndTime(myDevice);
    char totalHMS[25];
    char loopStartHMS[25];
    char loopEndHMS[25];
    secondsToHMSM(total, totalHMS, 25);
    if(loopStart >= 0.0 && loopEnd >= 0.0)
    {
        secondsToHMSM(loopStart, loopStartHMS, 25);
        secondsToHMSM(loopEnd, loopEndHMS, 25);
    }

#   ifndef HARDWARE_OPL3
    if(!recordWave)
#   endif
    {
        std::fprintf(stdout, " - Loop is turned %s\n", loopEnabled ? "ON" : "OFF");
        if(loopStart >= 0.0 && loopEnd >= 0.0)
            std::fprintf(stdout, " - Has loop points: %s ... %s\n", loopStartHMS, loopEndHMS);
        std::fprintf(stdout, "\n==========================================\n");
        flushout(stdout);

#   ifndef HARDWARE_OPL3
        SDL_PauseAudio(0);
#   endif

#   ifdef DEBUG_SEEKING_TEST
        int delayBeforeSeek = 50;
        std::fprintf(stdout, "DEBUG: === Random position set test is active! ===\n");
        flushout(stdout);
#   endif

#   ifndef HARDWARE_OPL3
        Uint8 buff[16384];
#   endif
        char posHMS[25];
        uint64_t milliseconds_prev = -1;
        while(!stop)
        {
#   ifndef HARDWARE_OPL3
            size_t got = (size_t)adl_playFormat(myDevice, 4096,
                                                buff,
                                                buff + g_audioFormat.containerSize,
                                                &g_audioFormat) * g_audioFormat.containerSize;
            if(got <= 0)
                break;
#   endif

#   ifdef DEBUG_TRACE_ALL_CHANNELS
            enum { TerminalColumns = 80 };
            char channelText[TerminalColumns + 1];
            char channelAttr[TerminalColumns + 1];
            adl_describeChannels(myDevice, channelText, channelAttr, sizeof(channelText));
            std::fprintf(stdout, "%*s\r", TerminalColumns, "");  // erase the line
            std::fprintf(stdout, "%s\n", channelText);
#   endif

#   ifndef DEBUG_TRACE_ALL_EVENTS
            double time_pos = adl_positionTell(myDevice);
            std::fprintf(stdout, "                                               \r");
            uint64_t milliseconds = static_cast<uint64_t>(time_pos * 1000.0);
            if(milliseconds != milliseconds_prev)
            {
                secondsToHMSM(time_pos, posHMS, 25);
                std::fprintf(stdout, "                                               \r");
                std::fprintf(stdout, "Time position: %s / %s\r", posHMS, totalHMS);
                flushout(stdout);
                milliseconds_prev = milliseconds;
            }
#   endif

#   ifndef HARDWARE_OPL3
            g_audioBuffer_lock.Lock();
            size_t pos = g_audioBuffer.size();
            g_audioBuffer.resize(pos + got);
            for(size_t p = 0; p < got; ++p)
                g_audioBuffer[pos + p] = buff[p];
            g_audioBuffer_lock.Unlock();

            const SDL_AudioSpec &spec = obtained;
            while(g_audioBuffer.size() > static_cast<size_t>(spec.samples + (spec.freq * g_audioFormat.sampleOffset) * OurHeadRoomLength))
            {
                SDL_Delay(1);
            }

#       ifdef DEBUG_SEEKING_TEST
            if(delayBeforeSeek-- <= 0)
            {
                delayBeforeSeek = rand() % 50;
                double seekTo = double((rand() % int(adl_totalTimeLength(myDevice)) - delayBeforeSeek - 1 ));
                adl_positionSeek(myDevice, seekTo);
            }
#       endif

#   else//HARDWARE_OPL3
            const double mindelay = 1.0 / NewTimerFreq;

            //__asm__ volatile("sti\nhlt");
            //usleep(10000);
            #ifdef __DJGPP__
            __dpmi_yield();
            #endif
            #ifdef __WATCOMC__
            //dpmi_dos_yield();
            mch_delay((unsigned int)(tick_delay * 1000.0));
            #endif
            static unsigned long PrevTimer = BIOStimer;
            const unsigned long CurTimer = BIOStimer;
            const double eat_delay = (CurTimer - PrevTimer) / (double)NewTimerFreq;
            PrevTimer = CurTimer;
            tick_delay = adl_tickEvents(myDevice, eat_delay, mindelay);
            if(adl_atEnd(myDevice) && tick_delay <= 0)
                stop = true;

            if(kbhit())
            {   // Quit on ESC key!
                int c = getch();
                if(c == 27)
                    stop = true;
            }

#   endif//HARDWARE_OPL3
        }
        std::fprintf(stdout, "                                               \n\n");
#   ifndef HARDWARE_OPL3
        SDL_CloseAudio();
#   endif
    }
#endif //OUTPUT_WAVE_ONLY

#ifndef HARDWARE_OPL3

#   ifndef OUTPUT_WAVE_ONLY
    else
#   endif //OUTPUT_WAVE_ONLY
    {
        std::string wave_out = musPath + ".wav";
        std::fprintf(stdout, " - Recording WAV file %s...\n", wave_out.c_str());
        std::fprintf(stdout, "\n==========================================\n");
        flushout(stdout);

        if(wave_open(sampleRate, wave_out.c_str()) == 0)
        {
            wave_enable_stereo();
            short buff[4096];
            int complete_prev = -1;
            while(!stop)
            {
                size_t got = (size_t)adl_play(myDevice, 4096, buff);
                if(got <= 0)
                    break;
                wave_write(buff, (long)got);

                int complete = static_cast<int>(std::floor(100.0 * adl_positionTell(myDevice) / total));
                flushout(stdout);
                if(complete_prev != complete)
                {
                    std::fprintf(stdout, "                                               \r");
                    std::fprintf(stdout, "Recording WAV... [%d%% completed]\r", complete);
                    std::fflush(stdout);
                    complete_prev = complete;
                }
            }
            wave_close();
            std::fprintf(stdout, "                                               \n\n");

            if(stop)
                std::fprintf(stdout, "Interrupted! Recorded WAV is incomplete, but playable!\n");
            else
                std::fprintf(stdout, "Completed!\n");
            flushout(stdout);
        }
        else
        {
            adl_close(myDevice);
            return 1;
        }
    }
#endif //HARDWARE_OPL3

#ifdef HARDWARE_OPL3

    #ifdef __DJGPP__
    // Fix the skewed clock and reset BIOS tick rate
    _farpokel(_dos_ds, 0x46C, BIOStimer_begin +
              (BIOStimer - BIOStimer_begin)
              * (0x1234DD / 65536.0) / NewTimerFreq);

    //disable();
    outportb(0x43, 0x34);
    outportb(0x40, 0);
    outportb(0x40, 0);
    //enable();
    #endif

    #ifdef __WATCOMC__
    outp(0x43, 0x34);
    outp(0x40, 0);
    outp(0x40, 0);
    #endif

    adl_panic(myDevice); //Shut up all sustaining notes

#endif

    adl_close(myDevice);

    return 0;
}
Exemplo n.º 9
0
static int dispatch_audio(short* outbuf, int length, espeak_EVENT* event)
{//======================================================================
	ENTER("dispatch_audio");

	int a_wave_can_be_played = fifo_is_command_enabled();

#ifdef DEBUG_ENABLED
	SHOW("*** dispatch_audio > uid=%d, [write=%p (%d bytes)], sample=%d, a_wave_can_be_played = %d\n",
			(event) ? event->unique_identifier : 0, wave_test_get_write_buffer(), 2*length,
			(event) ? event->sample : 0,
			a_wave_can_be_played);
#endif

	switch(my_mode)
	{
	case AUDIO_OUTPUT_PLAYBACK:
	{
		int event_type=0;
		if(event)
		{
			event_type = event->type;
		}

		if(event_type == espeakEVENT_SAMPLERATE)
		{
			voice_samplerate = event->id.number;

			if(out_samplerate != voice_samplerate)
			{
				if(out_samplerate != 0)
				{
					// sound was previously open with a different sample rate
					wave_close(my_audio);
					sleep(1);
				}
				out_samplerate = voice_samplerate;
				if(!wave_init(voice_samplerate))
				{
					err = EE_INTERNAL_ERROR;
					return(-1);
				}
				wave_set_callback_is_output_enabled( fifo_is_command_enabled);
				my_audio = wave_open("alsa");
				event_init();
			}
		}

		if (outbuf && length && a_wave_can_be_played)
		{
			wave_write (my_audio, (char*)outbuf, 2*length);
		}

		while(a_wave_can_be_played) {
			// TBD: some event are filtered here but some insight might be given
			// TBD: in synthesise.cpp for avoiding to create WORDs with size=0.
			// TBD: For example sentence "or ALT)." returns three words
			// "or", "ALT" and "".
			// TBD: the last one has its size=0.
			if (event && (event->type == espeakEVENT_WORD) && (event->length==0))
			{
				break;
			}
			espeak_ERROR a_error = event_declare(event);
			if (a_error != EE_BUFFER_FULL)
			{
				break;
			}
			SHOW_TIME("dispatch_audio > EE_BUFFER_FULL\n");
			usleep(10000);
			a_wave_can_be_played = fifo_is_command_enabled();
		}
	}
	break;

	case AUDIO_OUTPUT_RETRIEVAL:
		if (synth_callback)
		{
			synth_callback(outbuf, length, event);
		}
		break;

	case AUDIO_OUTPUT_SYNCHRONOUS:
	case AUDIO_OUTPUT_SYNCH_PLAYBACK:
		break;
	}

	if (!a_wave_can_be_played)
	{
		SHOW_TIME("dispatch_audio > synth must be stopped!\n");
	}

	SHOW_TIME("LEAVE dispatch_audio\n");

	return (a_wave_can_be_played==0); // 1 = stop synthesis, -1 = error
}