Esempio n. 1
0
static void *ThrHandler(void *Arg)
{
#ifndef NO_SOUND
    int J;

    // Spin until audiSo has been trashed
    for(RPtr=WPtr=0; SndRate&&SndData&&(SoundFD>=0);)
    {
#if defined(PULSE_AUDIO)
        if(SoundFD)
            pa_simple_write(SoundFD,SndData+RPtr,SND_BUFSIZE*sizeof(sample),0);
#elif defined(SUN_AUDIO)
        // Flush output first, don't care about return status. After this
        // write next buffer of audio data. This method produces a horrible
        // click on each buffer :( Any ideas, how to fix this?
        ioctl(SoundFD,AUDIO_DRAIN);
        write(SoundFD,SndData+RPtr,SND_BUFSIZE*sizeof(sample));
#elif defined(__PLAYBOOK__)

#else
        // We'll block here until next DMA buffer becomes free. It happens
        // once per SND_BUFSIZE/SndRate seconds.

        write(SoundFD,SndData+RPtr,SND_BUFSIZE*sizeof(sample));
#endif

        // Advance buffer pointer, clearing the buffer
        for(J=0; J<SND_BUFSIZE; ++J) SndData[RPtr++]=AUDIO_CONV(0);
        if(RPtr>=SndSize) RPtr=0;
    }
#endif

    return(0);
}
Esempio n. 2
0
/* note: gain is specified as gain*16 */
static int make_mixer_table (int gain)
{
	int count = NUM_VOICES * 128;
	int i;

	/* allocate memory */
	mixer_table = malloc (256 * NUM_VOICES);
	if (!mixer_table)
		return 1;

	/* find the middle of the table */
	mixer_lookup = mixer_table + (NUM_VOICES * 128);

	/* fill in the table */
	for (i = 0; i < count; i++)
	{
		int val = i * gain / (NUM_VOICES * 16);
		if (val > 127) val = 127;
		mixer_lookup[ i] = AUDIO_CONV(val);
		mixer_lookup[-i] = AUDIO_CONV(-val);
	}

	return 0;
}
Esempio n. 3
0
unsigned int WriteAudio(sample *Data,unsigned int Length)
{
    unsigned int J;

    // Require audio to be initialized
    if(!SndRate) return(0);

    // Copy audio samples
    for(J=0; (J<Length)&&(RPtr!=WPtr); ++J)
    {
        SndData[WPtr++]=AUDIO_CONV(Data[J]);
        if(WPtr>=SndSize) WPtr=0;
    }

    // Return number of samples copied
    return(J);
}
Esempio n. 4
0
unsigned int InitAudio(unsigned int Rate,unsigned int Latency)
{
#ifndef NO_SOUND
    int I,J,K;

    // Shut down audio, just to be sure
    TrashAudio();
#ifndef __PLAYBOOK__
    SoundFD     = -1;
    Thr         = 0;
#else
    SDL_AudioSpec AudioFormat;
#endif
    SndRate     = 0;
    SndSize     = 0;
    SndData     = 0;
    RPtr        = 0;
    WPtr        = 0;
    AudioPaused = 0;

    // Have to have at least 8kHz sampling rate and 1ms buffer
    if((Rate<8000)||!Latency) return(0);

    // Compute number of sound buffers
    SndSize=Rate*Latency/1000;

    // Allocate audio buffers
    SndData=(sample *)malloc(SndSize*sizeof(sample));
    if(!SndData) {
        TrashSound();
        return(0);
    }

#if defined(__PLAYBOOK__)
    SDL_InitSubSystem (SDL_INIT_AUDIO);

    /* Set SDL audio settings */
    AudioFormat.freq     = Rate;
    AudioFormat.format   = sizeof(sample)>1? AUDIO_S16:AUDIO_S8;
    AudioFormat.channels = 1;
    AudioFormat.samples  = SndSize/2;
    AudioFormat.callback = sdl_audio_callback;
    AudioFormat.userdata = 0;

    printf ("SDL sound driver initializing...\n");
    printf ("    --> (Frequency: %dhz, Latency: %dms)...",
            AudioFormat.freq,
            (AudioFormat.samples * 1000 / AudioFormat.freq) << 1);

    if (SDL_OpenAudio (&AudioFormat, NULL) < 0)
    {
        printf ("Failed\n");

        free(SndData);
        SndData = NULL;

        return 0;
    }

    printf ("OK\n");

    // Clear audio buffers
    for(J=0; J<SndSize; ++J) SndData[J]=AUDIO_CONV(0);

    // Thread expects valid SndRate!=0 at the start
    SndRate=Rate;

    SDL_PauseAudio (0);

#elif defined(PULSE_AUDIO)

    {
        // Configure PulseAudio sound
        pa_sample_spec PASpec;
        PASpec.format   = sizeof(sample)>1? PA_SAMPLE_S16LE:PA_SAMPLE_U8;
        PASpec.rate     = Rate;
        PASpec.channels = 1;
        // Try opening PulseAudio
        if(!(SoundFD=pa_simple_new(0,"EMULib",PA_STREAM_PLAYBACK,0,"playback",&PASpec,0,0,0)))
        {
            SoundFD=-1;
            return(0);
        }
    }

#elif defined(ESD_AUDIO)

    // ESD options for playing wave audio
    J=ESD_MONO|ESD_STREAM|ESD_PLAY|(sizeof(sample)>1? ESD_BITS16:ESD_BITS8);
    // Open ESD socket, fall back to /dev/dsp is no ESD
    if((SoundFD=esd_play_stream_fallback(J,Rate,0,0))<0) return(0);

#elif defined(SUN_AUDIO)

    // Open Sun's audio device
    if((SoundFD=open("/dev/audio",O_WRONLY|O_NONBLOCK))<0) return(0);

    // Sun's specific initialization should be here...
    // We assume, that it's set to 8000Hz u-law mono right now.

#else // !SUN_AUDIO

    // Open /dev/dsp audio device
    if((SoundFD=open("/dev/dsp",O_WRONLY))<0) return(0);
    // Set sound format
    J=sizeof(sample)>1? AFMT_S16_NE:AFMT_U8;
    I=ioctl(SoundFD,SNDCTL_DSP_SETFMT,&J)<0;
    // Set mono sound
    J=0;
    I|=ioctl(SoundFD,SNDCTL_DSP_STEREO,&J)<0;
    // Set sampling rate
    I|=ioctl(SoundFD,SNDCTL_DSP_SPEED,&Rate)<0;

    // Set buffer length and number of buffers
    J=K=SND_BITS|(SndSize<<16);
    I|=ioctl(SoundFD,SNDCTL_DSP_SETFRAGMENT,&J)<0;

    // Buffer length as n, not 2^n!
    if((J&0xFFFF)<=16) J=(J&0xFFFF0000)|(1<<(J&0xFFFF));
    K=SND_BUFSIZE|(SndSize<<16);

    // Check audio parameters
    I|=(J!=K)&&(((J>>16)<SndSize)||((J&0xFFFF)!=SND_BUFSIZE));

    // If something went wrong, drop out
    if(I) {
        TrashSound();
        return(0);
    }

#endif // !SUN_AUDIO

    // Create audio thread
#ifndef __PLAYBOOK__
    // SndSize now means the total buffer size
    SndSize*=SND_BUFSIZE;

    // Clear audio buffers
    for(J=0; J<SndSize; ++J) SndData[J]=AUDIO_CONV(0);

    // Thread expects valid SndRate!=0 at the start
    SndRate=Rate;

    if(pthread_create(&Thr,0,ThrHandler,0)) {
        TrashSound();
        SndRate=0;
        return(0);
    }
#endif

    // Done, return effective audio rate
    return(SndRate);
#else
    return 0;
#endif
}