Пример #1
0
static int
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    int valid_datatype = 0;
    
    //TODO: Sample rates etc
    __android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Open\n");

    this->hidden = SDL_malloc(sizeof(*(this->hidden)));
    if (!this->hidden) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    while ((!valid_datatype) && (test_format)) {
        this->spec.format = test_format;
        switch (test_format) {
        case AUDIO_S8:
            /*case AUDIO_S16LSB: */
            valid_datatype = 1;
            break;
        default:
            test_format = SDL_NextAudioFormat();
            break;
        }
    }
    
    return 1;
}
Пример #2
0
static int
AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format;

    if (iscapture) {
        /* TODO: implement capture */
        return SDL_SetError("Capture not supported on Android");
    }

    if (audioDevice != NULL) {
        return SDL_SetError("Only one audio device at a time please!");
    }

    audioDevice = this;
    
    this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }

    test_format = SDL_FirstAudioFormat(this->spec.format);
    while (test_format != 0) { /* no "UNKNOWN" constant */
        if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
            this->spec.format = test_format;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (test_format == 0) {
        /* Didn't find a compatible format :( */
        return SDL_SetError("No compatible audio format!");
    }

    if (this->spec.channels > 1) {
        this->spec.channels = 2;
    } else {
        this->spec.channels = 1;
    }

    if (this->spec.freq < 8000) {
        this->spec.freq = 8000;
    }
    if (this->spec.freq > 48000) {
        this->spec.freq = 48000;
    }

    /* TODO: pass in/return a (Java) device ID, also whether we're opening for input or output */
    this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
    SDL_CalculateAudioSpec(&this->spec);

    if (this->spec.samples == 0) {
        /* Init failed? */
        return SDL_SetError("Java-side initialization failed!");
    }

    return 0;
}
Пример #3
0
static int
ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format;

    SDL_assert((captureDevice == NULL) || !iscapture);
    SDL_assert((audioDevice == NULL) || iscapture);

    if (iscapture) {
        captureDevice = this;
    } else {
        audioDevice = this;
    }

    this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }

    test_format = SDL_FirstAudioFormat(this->spec.format);
    while (test_format != 0) { /* no "UNKNOWN" constant */
        if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
            this->spec.format = test_format;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (test_format == 0) {
        /* Didn't find a compatible format :( */
        return SDL_SetError("No compatible audio format!");
    }

    if (this->spec.channels > 1) {
        this->spec.channels = 2;
    } else {
        this->spec.channels = 1;
    }

    if (this->spec.freq < 8000) {
        this->spec.freq = 8000;
    }
    if (this->spec.freq > 48000) {
        this->spec.freq = 48000;
    }

    /* TODO: pass in/return a (Java) device ID */
    this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);

    if (this->spec.samples == 0) {
        /* Init failed? */
        return SDL_SetError("Java-side initialization failed!");
    }

    SDL_CalculateAudioSpec(&this->spec);

    return 0;
}
Пример #4
0
static int
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    HRESULT result;
    SDL_bool valid_format = SDL_FALSE;
    SDL_bool tried_format = SDL_FALSE;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    LPGUID guid = (LPGUID) handle;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Open the audio device */
    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
    if (result != DS_OK) {
        DSOUND_CloseDevice(this);
        return SetDSerror("DirectSoundCreate", result);
    }

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            tried_format = SDL_TRUE;
            this->spec.format = test_format;
            this->hidden->num_buffers = CreateSecondary(this, NULL);
            if (this->hidden->num_buffers > 0) {
                valid_format = SDL_TRUE;
            }
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        DSOUND_CloseDevice(this);
        if (tried_format) {
            return -1;  /* CreateSecondary() should have called SDL_SetError(). */
        }
        return SDL_SetError("DirectSound: Unsupported audio format");
    }

    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
    this->hidden->mixlen = this->spec.size;

    return 0;                   /* good to go. */
}
Пример #5
0
static int
ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format;

    SDL_assert((captureDevice == NULL) || !iscapture);
    SDL_assert((audioDevice == NULL) || iscapture);

    if (iscapture) {
        captureDevice = this;
    } else {
        audioDevice = this;
    }

    this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }

    test_format = SDL_FirstAudioFormat(this->spec.format);
    while (test_format != 0) { /* no "UNKNOWN" constant */
        if ((test_format == AUDIO_U8) ||
			(test_format == AUDIO_S16) ||
			(test_format == AUDIO_F32)) {
            this->spec.format = test_format;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (test_format == 0) {
        /* Didn't find a compatible format :( */
        return SDL_SetError("No compatible audio format!");
    }

    if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
        return -1;
    }

    SDL_CalculateAudioSpec(&this->spec);

    return 0;
}
Пример #6
0
static int
NDSAUD_OpenDevice(_THIS, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    int valid_datatype = 0;

    this->hidden = SDL_malloc(sizeof(*(this->hidden)));
    if (!this->hidden) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    while ((!valid_datatype) && (test_format)) {
        this->spec.format = test_format;
        switch (test_format) {
        case AUDIO_S8:
            /*case AUDIO_S16LSB: */
            valid_datatype = 1;
            break;
        default:
            test_format = SDL_NextAudioFormat();
            break;
        }
    }

#if 0
    /* set the generic sound parameters */
    setGenericSound(22050,      /* sample rate */
                    127,        /* volume */
                    64,         /* panning/balance */
                    0);         /* sound format */
#endif

    return 1;
}
Пример #7
0
static int
PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
{
    struct SDL_PrivateAudioData *h = NULL;
    Uint16 test_format = 0;
    pa_sample_spec paspec;
    pa_buffer_attr paattr;
    pa_channel_map pacmap;
    pa_stream_flags_t flags = 0;
    int state = 0;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    h = this->hidden;

    paspec.format = PA_SAMPLE_INVALID;

    /* Try for a closest match on audio format */
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         (paspec.format == PA_SAMPLE_INVALID) && test_format;) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        switch (test_format) {
        case AUDIO_U8:
            paspec.format = PA_SAMPLE_U8;
            break;
        case AUDIO_S16LSB:
            paspec.format = PA_SAMPLE_S16LE;
            break;
        case AUDIO_S16MSB:
            paspec.format = PA_SAMPLE_S16BE;
            break;
        case AUDIO_S32LSB:
            paspec.format = PA_SAMPLE_S32LE;
            break;
        case AUDIO_S32MSB:
            paspec.format = PA_SAMPLE_S32BE;
            break;
        case AUDIO_F32LSB:
            paspec.format = PA_SAMPLE_FLOAT32LE;
            break;
        case AUDIO_F32MSB:
            paspec.format = PA_SAMPLE_FLOAT32BE;
            break;
        default:
            paspec.format = PA_SAMPLE_INVALID;
            break;
        }
        if (paspec.format == PA_SAMPLE_INVALID) {
            test_format = SDL_NextAudioFormat();
        }
    }
    if (paspec.format == PA_SAMPLE_INVALID) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("Couldn't find any hardware audio formats");
    }
    this->spec.format = test_format;

    /* Calculate the final parameters for this audio specification */
#ifdef PA_STREAM_ADJUST_LATENCY
    this->spec.samples /= 2; /* Mix in smaller chunck to avoid underruns */
#endif
    SDL_CalculateAudioSpec(&this->spec);

    /* Allocate mixing buffer */
    h->mixlen = this->spec.size;
    h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen);
    if (h->mixbuf == NULL) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);

    paspec.channels = this->spec.channels;
    paspec.rate = this->spec.freq;

    /* Reduced prebuffering compared to the defaults. */
#ifdef PA_STREAM_ADJUST_LATENCY
    /* 2x original requested bufsize */
    paattr.tlength = h->mixlen * 4;
    paattr.prebuf = -1;
    paattr.maxlength = -1;
    /* -1 can lead to pa_stream_writable_size() >= mixlen never being true */
    paattr.minreq = h->mixlen;
    flags = PA_STREAM_ADJUST_LATENCY;
#else
    paattr.tlength = h->mixlen*2;
    paattr.prebuf = h->mixlen*2;
    paattr.maxlength = h->mixlen*2;
    paattr.minreq = h->mixlen;
#endif

    /* The SDL ALSA output hints us that we use Windows' channel mapping */
    /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */
    PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels,
                                        PA_CHANNEL_MAP_WAVEEX);

    /* Set up a new main loop */
    if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("pa_mainloop_new() failed");
    }

    h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
    h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName());
    if (!h->context) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("pa_context_new() failed");
    }

    /* Connect to the PulseAudio server */
    if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("Could not setup connection to PulseAudio");
    }

    do {
        if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
            PULSEAUDIO_CloseDevice(this);
            return SDL_SetError("pa_mainloop_iterate() failed");
        }
        state = PULSEAUDIO_pa_context_get_state(h->context);
        if (!PA_CONTEXT_IS_GOOD(state)) {
            PULSEAUDIO_CloseDevice(this);
            return SDL_SetError("Could not connect to PulseAudio");
        }
    } while (state != PA_CONTEXT_READY);

    h->stream = PULSEAUDIO_pa_stream_new(
        h->context,
        "Simple DirectMedia Layer", /* stream description */
        &paspec,    /* sample format spec */
        &pacmap     /* channel map */
        );

    if (h->stream == NULL) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("Could not set up PulseAudio stream");
    }

    if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags,
            NULL, NULL) < 0) {
        PULSEAUDIO_CloseDevice(this);
        return SDL_SetError("Could not connect PulseAudio stream");
    }

    do {
        if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
            PULSEAUDIO_CloseDevice(this);
            return SDL_SetError("pa_mainloop_iterate() failed");
        }
        state = PULSEAUDIO_pa_stream_get_state(h->stream);
        if (!PA_STREAM_IS_GOOD(state)) {
            PULSEAUDIO_CloseDevice(this);
            return SDL_SetError("Could not create to PulseAudio stream");
        }
    } while (state != PA_STREAM_READY);

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #8
0
static int
XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
{
    HRESULT result = S_OK;
    WAVEFORMATEX waveformat;
    int valid_format = 0;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    IXAudio2 *ixa2 = NULL;
    IXAudio2SourceVoice *source = NULL;
    UINT32 devId = 0;  /* 0 == system default device. */

	static IXAudio2VoiceCallbackVtbl callbacks_vtable = {
	    VoiceCBOnVoiceProcessPassStart,
        VoiceCBOnVoiceProcessPassEnd,
        VoiceCBOnStreamEnd,
        VoiceCBOnBufferStart,
        VoiceCBOnBufferEnd,
        VoiceCBOnLoopEnd,
        VoiceCBOnVoiceError
	};

	static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };

	// add WIN_CoInitialize() and WIN_CoUninitialize here;
	// to avoid XAudio2Create return hr	0x800401f0 ипн╢╣Всц CoInitialize;

    if (iscapture) {
        SDL_SetError("XAudio2: capture devices unsupported.");
        return 0;
    } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
        SDL_SetError("XAudio2: XAudio2Create() failed.");
        return 0;
    }

    if (devname != NULL) {
        UINT32 devcount = 0;
        UINT32 i = 0;

        if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
            IXAudio2_Release(ixa2);
            SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed.");
            return 0;
        }
        for (i = 0; i < devcount; i++) {
            XAUDIO2_DEVICE_DETAILS details;
            if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
                char *str = utf16_to_utf8(details.DisplayName);
                if (str != NULL) {
                    const int match = (SDL_strcmp(str, devname) == 0);
                    SDL_free(str);
                    if (match) {
                        devId = i;
                        break;
                    }
                }
            }
        }

        if (i == devcount) {
            IXAudio2_Release(ixa2);
            SDL_SetError("XAudio2: Requested device not found.");
            return 0;
        }
    }

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        IXAudio2_Release(ixa2);
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    this->hidden->ixa2 = ixa2;
    this->hidden->semaphore = CreateSemaphore(NULL, 1, 2, NULL);
    if (this->hidden->semaphore == NULL) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: CreateSemaphore() failed!");
        return 0;
    }

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            this->spec.format = test_format;
            valid_format = 1;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: Unsupported audio format");
        return 0;
    }

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* We feed a Source, it feeds the Mastering, which feeds the device. */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        XAUDIO2_CloseDevice(this);
        SDL_OutOfMemory();
        return 0;
    }
    this->hidden->nextbuf = this->hidden->mixbuf;
    SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen);

    /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On
       Xbox360, this means 5.1 output, but on Windows, it means "figure out
       what the system has." It might be preferable to let XAudio2 blast
       stereo output to appropriate surround sound configurations
       instead of clamping to 2 channels, even though we'll configure the
       Source Voice for whatever number of channels you supply. */
    result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering,
                                           XAUDIO2_DEFAULT_CHANNELS,
                                           this->spec.freq, 0, devId, NULL);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: Couldn't create mastering voice");
        return 0;
    }

    SDL_zero(waveformat);
    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
        waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    } else {
        waveformat.wFormatTag = WAVE_FORMAT_PCM;
    }
    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
    waveformat.nChannels = this->spec.channels;
    waveformat.nSamplesPerSec = this->spec.freq;
    waveformat.nBlockAlign =
        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
    waveformat.nAvgBytesPerSec =
        waveformat.nSamplesPerSec * waveformat.nBlockAlign;

    result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat,
                                        XAUDIO2_VOICE_NOSRC |
                                        XAUDIO2_VOICE_NOPITCH,
                                        1.0f, &callbacks, NULL, NULL);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: Couldn't create source voice");
        return 0;
    }
    this->hidden->source = source;

    /* Start everything playing! */
    result = IXAudio2_StartEngine(ixa2);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: Couldn't start engine");
        return 0;
    }

    result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        SDL_SetError("XAudio2: Couldn't start source voice");
        return 0;
    }

    return 1; /* good to go. */
}
Пример #9
0
static int
SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
{
    int bytes;
    SDL_AudioFormat test_format = 0, format = 0;
    FSSampleFormat fs_format;
    FSStreamDescription desc;
    DirectResult ret;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Try for a closest match on audio format */
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !format && test_format;) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        switch (test_format) {
        case AUDIO_U8:
            fs_format = FSSF_U8;
            bytes = 1;
            format = 1;
            break;
        case AUDIO_S16SYS:
            fs_format = FSSF_S16;
            bytes = 2;
            format = 1;
            break;
        case AUDIO_S32SYS:
            fs_format = FSSF_S32;
            bytes = 4;
            format = 1;
            break;
        case AUDIO_F32SYS:
            fs_format = FSSF_FLOAT;
            bytes = 4;
            format = 1;
            break;
        default:
            format = 0;
            break;
        }
        if (!format) {
            test_format = SDL_NextAudioFormat();
        }
    }

    if (format == 0) {
        SDL_FS_CloseDevice(this);
        return SDL_SetError("Couldn't find any hardware audio formats");
    }
    this->spec.format = test_format;

    /* Retrieve the main sound interface. */
    ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
    if (ret) {
        SDL_FS_CloseDevice(this);
        return SDL_SetError("Unable to initialize FusionSound: %d", ret);
    }

    this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;

    /* Fill stream description. */
    desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
        FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
    desc.samplerate = this->spec.freq;
    desc.buffersize = this->spec.size * FUSION_BUFFERS;
    desc.channels = this->spec.channels;
    desc.prebuffer = 10;
    desc.sampleformat = fs_format;

    ret =
        this->hidden->fs->CreateStream(this->hidden->fs, &desc,
                                       &this->hidden->stream);
    if (ret) {
        SDL_FS_CloseDevice(this);
        return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
    }

    /* See what we got */
    desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
        FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
    ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);

    this->spec.freq = desc.samplerate;
    this->spec.size =
        desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
    this->spec.channels = desc.channels;

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        SDL_FS_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #10
0
static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	char audiodev[1024];
	int format;
	int value;
	Uint16 test_format;

	/* Reset the timer synchronization flag */
	frame_ticks = 0.0;

	/* Open the audio device */
	audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
	if ( audio_fd < 0 ) {
		SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
		return(-1);
	}
	mixbuf = NULL;

#ifdef USE_BLOCKING_WRITES
	/* Make the file descriptor use blocking writes with fcntl() */
	{ long flags;
		flags = fcntl(audio_fd, F_GETFL);
		flags &= ~O_NONBLOCK;
		if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) {
			SDL_SetError("Couldn't set audio blocking mode");
			return(-1);
		}
	}
#endif

	/* Get a list of supported hardware formats */
	if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) {
		SDL_SetError("Couldn't get audio format list");
		return(-1);
	}

	/* Try for a closest match on audio format */
	format = 0;
	for ( test_format = SDL_FirstAudioFormat(spec->format);
						! format && test_format; ) {
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
		switch ( test_format ) {
			case AUDIO_U8:
				if ( value & AFMT_U8 ) {
					format = AFMT_U8;
				}
				break;
			case AUDIO_S8:
				if ( value & AFMT_S8 ) {
					format = AFMT_S8;
				}
				break;
			case AUDIO_S16LSB:
				if ( value & AFMT_S16_LE ) {
					format = AFMT_S16_LE;
				}
				break;
			case AUDIO_S16MSB:
				if ( value & AFMT_S16_BE ) {
					format = AFMT_S16_BE;
				}
				break;
			case AUDIO_U16LSB:
				if ( value & AFMT_U16_LE ) {
					format = AFMT_U16_LE;
				}
				break;
			case AUDIO_U16MSB:
				if ( value & AFMT_U16_BE ) {
					format = AFMT_U16_BE;
				}
				break;
			default:
				format = 0;
				break;
		}
		if ( ! format ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	if ( format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	spec->format = test_format;

	/* Set the audio format */
	value = format;
	if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
						(value != format) ) {
		SDL_SetError("Couldn't set audio format");
		return(-1);
	}

	/* Set the number of channels of output */
	value = spec->channels;
#ifdef SNDCTL_DSP_CHANNELS
	if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) {
#endif
		value = (spec->channels > 1);
		ioctl(audio_fd, SNDCTL_DSP_STEREO, &value);
		value = (value ? 2 : 1);
#ifdef SNDCTL_DSP_CHANNELS
	}
#endif
	spec->channels = value;

	/* Because some drivers don't allow setting the buffer size
	   after setting the format, we must re-open the audio device
	   once we know what format and channels are supported
	 */
	if ( DSP_ReopenAudio(this, audiodev, format, spec) < 0 ) {
		/* Error is set by DSP_ReopenAudio() */
		return(-1);
	}

	/* Allocate mixing buffer */
	mixlen = spec->size;
	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
	if ( mixbuf == NULL ) {
		return(-1);
	}
	memset(mixbuf, spec->silence, spec->size);

#ifndef USE_BLOCKING_WRITES
	/* Check to see if we need to use select() workaround */
	{ char *workaround;
		workaround = getenv("SDL_DSP_NOSELECT");
		if ( workaround ) {
			frame_ticks = (float)(spec->samples*1000)/spec->freq;
			next_frame = SDL_GetTicks()+frame_ticks;
		}
	}
#endif /* !USE_BLOCKING_WRITES */

	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #11
0
static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	AuElement elms[3];
	int buffer_size;
	Uint16 test_format, format;

	this->hidden->mixbuf = NULL;

	/* Try for a closest match on audio format */
	format = 0;
	for ( test_format = SDL_FirstAudioFormat(spec->format);
						! format && test_format; ) {
		format = sdlformat_to_auformat(test_format);

		if (format == AuNone) {
			test_format = SDL_NextAudioFormat();
		}
	}
	if ( format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	spec->format = test_format;

	this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
	if (this->hidden->aud == 0)
	{
		SDL_SetError("Couldn't open connection to NAS server");
		return (-1);
	}
	
	this->hidden->dev = find_device(this, spec->channels);
	if ((this->hidden->dev == AuNone) || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) {
		AuCloseServer(this->hidden->aud);
		this->hidden->aud = 0;
		SDL_SetError("Couldn't find a fitting playback device on NAS server");
		return (-1);
	}
	
	buffer_size = spec->freq;
	if (buffer_size < 4096)
		buffer_size = 4096; 

	if (buffer_size > 32768)
		buffer_size = 32768; /* So that the buffer won't get unmanageably big. */

	/* Calculate the final parameters for this audio specification */
	SDL_CalculateAudioSpec(spec);

	this2 = this->hidden;

	AuMakeElementImportClient(elms, spec->freq, format, spec->channels, AuTrue,
				buffer_size, buffer_size / 4, 0, NULL);
	AuMakeElementExportDevice(elms+1, 0, this->hidden->dev, spec->freq,
				AuUnlimitedSamples, 0, NULL);
	AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL);
	AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, this->hidden->flow,
				event_handler, (AuPointer) NULL);

	AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);

	/* Allocate mixing buffer */
	this->hidden->mixlen = spec->size;
	this->hidden->mixbuf = (Uint8 *)SDL_AllocAudioMem(this->hidden->mixlen);
	if ( this->hidden->mixbuf == NULL ) {
		return(-1);
	}
	memset(this->hidden->mixbuf, spec->silence, spec->size);

	/* Get the parent process id (we're the parent of the audio thread) */
	this->hidden->parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #12
0
static int
BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
{
    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
    SDL_AudioFormat format = 0;
    audio_info_t info;

    /* We don't care what the devname is...we'll try to open anything. */
    /*  ...but default to first name in the list... */
    if (devname == NULL) {
        devname = SDL_GetAudioDeviceName(0, iscapture);
        if (devname == NULL) {
            SDL_SetError("No such audio device");
            return 0;
        }
    }

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Open the audio device */
    this->hidden->audio_fd = open(devname, flags, 0);
    if (this->hidden->audio_fd < 0) {
        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
        return 0;
    }

    AUDIO_INITINFO(&info);

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    /* Set to play mode */
    info.mode = AUMODE_PLAY;
    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
        BSDAUDIO_CloseDevice(this);
        SDL_SetError("Couldn't put device into play mode");
        return 0;
    }

    AUDIO_INITINFO(&info);
    for (format = SDL_FirstAudioFormat(this->spec.format);
         format; format = SDL_NextAudioFormat()) {
        switch (format) {
        case AUDIO_U8:
            info.play.encoding = AUDIO_ENCODING_ULINEAR;
            info.play.precision = 8;
            break;
        case AUDIO_S8:
            info.play.encoding = AUDIO_ENCODING_SLINEAR;
            info.play.precision = 8;
            break;
        case AUDIO_S16LSB:
            info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
            info.play.precision = 16;
            break;
        case AUDIO_S16MSB:
            info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
            info.play.precision = 16;
            break;
        case AUDIO_U16LSB:
            info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
            info.play.precision = 16;
            break;
        case AUDIO_U16MSB:
            info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
            info.play.precision = 16;
            break;
        default:
            continue;
        }

        if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
            break;
        }
    }

    if (!format) {
        BSDAUDIO_CloseDevice(this);
        SDL_SetError("No supported encoding for 0x%x", this->spec.format);
        return 0;
    }

    this->spec.format = format;

    AUDIO_INITINFO(&info);
    info.play.channels = this->spec.channels;
    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
        this->spec.channels = 1;
    }
    AUDIO_INITINFO(&info);
    info.play.sample_rate = this->spec.freq;
    info.blocksize = this->spec.size;
    info.hiwat = 5;
    info.lowat = 3;
    (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
    (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
    this->spec.freq = info.play.sample_rate;
    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        BSDAUDIO_CloseDevice(this);
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

    BSDAUDIO_Status(this);

    /* We're ready to rock and roll. :-) */
    return (0);
}
Пример #13
0
static int
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    int valid_datatype = 0;
    MMRESULT result;
    WAVEFORMATEX waveformat;
    UINT devId = WAVE_MAPPER;  /* WAVE_MAPPER == choose system's default */
    UINT i;

    if (handle != NULL) {  /* specific device requested? */
        /* -1 because we increment the original value to avoid NULL. */
        const size_t val = ((size_t) handle) - 1;
        devId = (UINT) val;
    }

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Initialize the wavebuf structures for closing */
    for (i = 0; i < NUM_BUFFERS; ++i)
        this->hidden->wavebuf[i].dwUser = 0xFFFF;

    if (this->spec.channels > 2)
        this->spec.channels = 2;        /* !!! FIXME: is this right? */

    while ((!valid_datatype) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            this->spec.format = test_format;
            if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
                valid_datatype = 1;
            } else {
                test_format = SDL_NextAudioFormat();
            }
            break;

        default:
            test_format = SDL_NextAudioFormat();
            break;
        }
    }

    if (!valid_datatype) {
        WINMM_CloseDevice(this);
        return SDL_SetError("Unsupported audio format");
    }

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* Open the audio device */
    if (iscapture) {
        result = waveInOpen(&this->hidden->hin, devId, &waveformat,
                             (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
                             CALLBACK_FUNCTION);
    } else {
        result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
                             (DWORD_PTR) FillSound, (DWORD_PTR) this,
                             CALLBACK_FUNCTION);
    }

    if (result != MMSYSERR_NOERROR) {
        WINMM_CloseDevice(this);
        return SetMMerror("waveOutOpen()", result);
    }
#ifdef SOUND_DEBUG
    /* Check the sound device we retrieved */
    {
        WAVEOUTCAPS caps;

        result = waveOutGetDevCaps((UINT) this->hidden->hout,
                                   &caps, sizeof(caps));
        if (result != MMSYSERR_NOERROR) {
            WINMM_CloseDevice(this);
            return SetMMerror("waveOutGetDevCaps()", result);
        }
        printf("Audio device: %s\n", caps.szPname);
    }
#endif

    /* Create the audio buffer semaphore */
    this->hidden->audio_sem =
        CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
    if (this->hidden->audio_sem == NULL) {
        WINMM_CloseDevice(this);
        return SDL_SetError("Couldn't create semaphore");
    }

    /* Create the sound buffers */
    this->hidden->mixbuf =
        (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
    if (this->hidden->mixbuf == NULL) {
        WINMM_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    for (i = 0; i < NUM_BUFFERS; ++i) {
        SDL_memset(&this->hidden->wavebuf[i], 0,
                   sizeof(this->hidden->wavebuf[i]));
        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
        this->hidden->wavebuf[i].lpData =
            (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
        result = waveOutPrepareHeader(this->hidden->hout,
                                      &this->hidden->wavebuf[i],
                                      sizeof(this->hidden->wavebuf[i]));
        if (result != MMSYSERR_NOERROR) {
            WINMM_CloseDevice(this);
            return SetMMerror("waveOutPrepareHeader()", result);
        }
    }

    return 0;                   /* Ready to go! */
}
Пример #14
0
static int
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
{
    int status = 0;
    int format = 0;
    SDL_AudioFormat test_format = 0;
    int found = 0;
    snd_pcm_channel_setup_t csetup;
    snd_pcm_channel_params_t cparams;

    /* Initialize all variables that we clean on shutdown */
    this->hidden =
        (struct SDL_PrivateAudioData *) SDL_calloc(1,
                                                   (sizeof
                                                    (struct
                                                     SDL_PrivateAudioData)));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));

    /* Initialize channel transfer parameters to default */
    QSA_InitAudioParams(&cparams);

    /* Initialize channel direction: capture or playback */
    this->hidden->iscapture = iscapture;

    /* Find deviceid and cardid by device name for playback */
    if ((!this->hidden->iscapture) && (devname != NULL)) {
        uint32_t device;
        int32_t status;

        /* Search in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_playback_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_playback_device[device].deviceno;
                this->hidden->cardno = qsa_playback_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_playback_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such playback device");
            }
        } while (1);
    }

    /* Find deviceid and cardid by device name for capture */
    if ((this->hidden->iscapture) && (devname != NULL)) {
        /* Search in the capture devices */
        uint32_t device;
        int32_t status;

        /* Searching in the playback devices */
        device = 0;
        do {
            status = SDL_strcmp(qsa_capture_device[device].name, devname);
            if (status == 0) {
                /* Found requested device */
                this->hidden->deviceno = qsa_capture_device[device].deviceno;
                this->hidden->cardno = qsa_capture_device[device].cardno;
                break;
            }
            device++;
            if (device >= qsa_capture_devices) {
                QSA_CloseDevice(this);
                return SDL_SetError("No such capture device");
            }
        } while (1);
    }

    /* Check if SDL requested default audio device */
    if (devname == NULL) {
        /* Open system default audio device */
        if (!this->hidden->iscapture) {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_PLAYBACK);
        } else {
            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
                                            &this->hidden->cardno,
                                            &this->hidden->deviceno,
                                            SND_PCM_OPEN_CAPTURE);
        }
    } else {
        /* Open requested audio device */
        if (!this->hidden->iscapture) {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_PLAYBACK);
        } else {
            status =
                snd_pcm_open(&this->hidden->audio_handle,
                             this->hidden->cardno, this->hidden->deviceno,
                             SND_PCM_OPEN_CAPTURE);
        }
    }

    /* Check if requested device is opened */
    if (status < 0) {
        this->hidden->audio_handle = NULL;
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_open", status);
    }

    if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
        /* Disable QSA MMAP plugin for buggy audio drivers */
        status =
            snd_pcm_plugin_set_disable(this->hidden->audio_handle,
                                       PLUGIN_DISABLE_MMAP);
        if (status < 0) {
            QSA_CloseDevice(this);
            return QSA_SetError("snd_pcm_plugin_set_disable", status);
        }
    }

    /* Try for a closest match on audio format */
    format = 0;
    /* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
    found = 0;

    for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
        /* if match found set format to equivalent QSA format */
        switch (test_format) {
        case AUDIO_U8:
            {
                format = SND_PCM_SFMT_U8;
                found = 1;
            }
            break;
        case AUDIO_S8:
            {
                format = SND_PCM_SFMT_S8;
                found = 1;
            }
            break;
        case AUDIO_S16LSB:
            {
                format = SND_PCM_SFMT_S16_LE;
                found = 1;
            }
            break;
        case AUDIO_S16MSB:
            {
                format = SND_PCM_SFMT_S16_BE;
                found = 1;
            }
            break;
        case AUDIO_U16LSB:
            {
                format = SND_PCM_SFMT_U16_LE;
                found = 1;
            }
            break;
        case AUDIO_U16MSB:
            {
                format = SND_PCM_SFMT_U16_BE;
                found = 1;
            }
            break;
        case AUDIO_S32LSB:
            {
                format = SND_PCM_SFMT_S32_LE;
                found = 1;
            }
            break;
        case AUDIO_S32MSB:
            {
                format = SND_PCM_SFMT_S32_BE;
                found = 1;
            }
            break;
        case AUDIO_F32LSB:
            {
                format = SND_PCM_SFMT_FLOAT_LE;
                found = 1;
            }
            break;
        case AUDIO_F32MSB:
            {
                format = SND_PCM_SFMT_FLOAT_BE;
                found = 1;
            }
            break;
        default:
            {
                break;
            }
        }

        if (!found) {
            test_format = SDL_NextAudioFormat();
        }
    }

    /* assumes test_format not 0 on success */
    if (test_format == 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Couldn't find any hardware audio formats");
    }

    this->spec.format = test_format;

    /* Set the audio format */
    cparams.format.format = format;

    /* Set mono/stereo/4ch/6ch/8ch audio */
    cparams.format.voices = this->spec.channels;

    /* Set rate */
    cparams.format.rate = this->spec.freq;

    /* Setup the transfer parameters according to cparams */
    status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_channel_params", status);
    }

    /* Make sure channel is setup right one last time */
    SDL_memset(&csetup, 0, sizeof(csetup));
    if (!this->hidden->iscapture) {
        csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    } else {
        csetup.channel = SND_PCM_CHANNEL_CAPTURE;
    }

    /* Setup an audio channel */
    if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
        QSA_CloseDevice(this);
        return SDL_SetError("QSA: Unable to setup channel");
    }

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    this->hidden->pcm_len = this->spec.size;

    if (this->hidden->pcm_len == 0) {
        this->hidden->pcm_len =
            csetup.buf.block.frag_size * this->spec.channels *
            (snd_pcm_format_width(format) / 8);
    }

    /*
     * Allocate memory to the audio buffer and initialize with silence
     *  (Note that buffer size must be a multiple of fragment size, so find
     *  closest multiple)
     */
    this->hidden->pcm_buf =
        (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
    if (this->hidden->pcm_buf == NULL) {
        QSA_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->pcm_buf, this->spec.silence,
               this->hidden->pcm_len);

    /* get the file descriptor */
    if (!this->hidden->iscapture) {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_PLAYBACK);
    } else {
        this->hidden->audio_fd =
            snd_pcm_file_descriptor(this->hidden->audio_handle,
                                    SND_PCM_CHANNEL_CAPTURE);
    }

    if (this->hidden->audio_fd < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_file_descriptor", status);
    }

    /* Prepare an audio channel */
    if (!this->hidden->iscapture) {
        /* Prepare audio playback */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_PLAYBACK);
    } else {
        /* Prepare audio capture */
        status =
            snd_pcm_plugin_prepare(this->hidden->audio_handle,
                                   SND_PCM_CHANNEL_CAPTURE);
    }

    if (status < 0) {
        QSA_CloseDevice(this);
        return QSA_SetError("snd_pcm_plugin_prepare", status);
    }

    /* We're really ready to rock and roll. :-) */
    return 0;
}
Пример #15
0
int DART_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
  Uint16 test_format = SDL_FirstAudioFormat(spec->format);
  int valid_datatype = 0;
  MCI_AMP_OPEN_PARMS AmpOpenParms;
  MCI_GENERIC_PARMS GenericParms;
  int iDeviceOrd = 0; 
  int bOpenShared = 1; 
  int iBits = 16; 
  int iFreq = 44100; 
  int iChannels = 2; 
  int iNumBufs = 2;  
  int iBufSize;
  int iOpenMode;
  int iSilence;
  int rc;

  
  SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
  
  AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16));

  iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID;
  if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE;

  rc = mciSendCommand( 0, MCI_OPEN,
                       iOpenMode,
		       (PVOID) &AmpOpenParms, 0);
  if (rc!=MCIERR_SUCCESS) 
    return (-1);
  
  
  iDeviceOrd = AmpOpenParms.usDeviceID;

  
  if (spec->channels > 2)
    spec->channels = 2;  

  while ((!valid_datatype) && (test_format)) {
    spec->format = test_format;
    valid_datatype = 1;
    switch (test_format) {
      case AUDIO_U8:
        
        iSilence = 0x80;
        iBits = 8;
        break;

      case AUDIO_S16LSB:
        
        iSilence = 0x00;
        iBits = 16;
        break;

      default:
        valid_datatype = 0;
        test_format = SDL_NextAudioFormat();
        break;
    }
  }

  if (!valid_datatype) { 
    
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("Unsupported audio format");
    return (-1);
  }

  iFreq = spec->freq;
  iChannels = spec->channels;
  
  SDL_CalculateAudioSpec(spec);
  iBufSize = spec->size;

  
  SDL_memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS));
  _this->hidden->MixSetupParms.ulBitsPerSample = iBits;
  _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
  _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq;
  _this->hidden->MixSetupParms.ulChannels = iChannels;
  _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY;
  _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc;
  rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP,
                       MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
                       &(_this->hidden->MixSetupParms), 0);
  if (rc!=MCIERR_SUCCESS)
  { 
    
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("Audio device doesn't support requested audio format");
    return(-1);
  }
  
  rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
                      MCI_WAIT | MCI_MIXSETUP_INIT,
                      &(_this->hidden->MixSetupParms), 0);
  if (rc!=MCIERR_SUCCESS)
  { 
    
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("Audio device could not be set up");
    return(-1);
  }
  
  
  
  _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs);
  if (!(_this->hidden->pMixBuffers))
  { 
    
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("Not enough memory for audio buffer descriptors");
    return(-1);
  }
  
  
  _this->hidden->BufferParms.ulNumBuffers = iNumBufs;               
  _this->hidden->BufferParms.ulBufferSize = iBufSize;               
  _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; 
  
  rc = mciSendCommand(iDeviceOrd, MCI_BUFFER,
                      MCI_WAIT | MCI_ALLOCATE_MEMORY,
                      &(_this->hidden->BufferParms), 0);
  if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0))
  { 
    
    SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("DART could not allocate buffers");
    return(-1);
  }
  
  {
    int i;
    for (i=0; i<iNumBufs; i++)
    {
      pMixBufferDesc pBufferDesc = (pMixBufferDesc) SDL_malloc(sizeof(tMixBufferDesc));;
      
      if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc))
      { 
        
        
        { int j;
          for (j=0; j<i; j++) SDL_free((void *)(_this->hidden->pMixBuffers[j].ulUserParm));
        }
        
        mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
        SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
        SDL_SetError("Error at internal buffer check");
        return(-1);
      }
      pBufferDesc->iBufferUsage = BUFFER_EMPTY;
      pBufferDesc->pSDLAudioDevice = _this;

      _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize;
      _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; 
      _this->hidden->pMixBuffers[i].ulFlags = 0; 
                                            
                                            
      SDL_memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize);
    }
  }
  _this->hidden->iNextFreeBuffer = 0;
  _this->hidden->iLastPlayedBuf = -1;
  
  if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR)
  {
    
    {
      int i;
      for (i=0; i<iNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm));
    }
    mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0);
    SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL;
    mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
    SDL_SetError("Could not create event semaphore");
    return(-1);
  }

  
  _this->hidden->iCurrDeviceOrd = iDeviceOrd;
  _this->hidden->iCurrFreq = iFreq;
  _this->hidden->iCurrBits = iBits;
  _this->hidden->iCurrChannels = iChannels;
  _this->hidden->iCurrNumBufs = iNumBufs;
  _this->hidden->iCurrBufSize = iBufSize;

  return (0);
}
Пример #16
0
static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int                  status;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_format_t     format;
	snd_pcm_uframes_t    frames;
	Uint16               test_format;

	/* Open the audio device */
	/* Name of device should depend on # channels in spec */
	status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);

	if ( status < 0 ) {
		SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status));
		return(-1);
	}

	/* Figure out what the hardware is capable of */
	snd_pcm_hw_params_alloca(&hwparams);
	status = SDL_NAME(snd_pcm_hw_params_any)(pcm_handle, hwparams);
	if ( status < 0 ) {
		SDL_SetError("Couldn't get hardware config: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}

	/* SDL only uses interleaved sample output */
	status = SDL_NAME(snd_pcm_hw_params_set_access)(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set interleaved access: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}

	/* Try for a closest match on audio format */
	status = -1;
	for ( test_format = SDL_FirstAudioFormat(spec->format);
	      test_format && (status < 0); ) {
		switch ( test_format ) {
			case AUDIO_U8:
				format = SND_PCM_FORMAT_U8;
				break;
			case AUDIO_S8:
				format = SND_PCM_FORMAT_S8;
				break;
			case AUDIO_S16LSB:
				format = SND_PCM_FORMAT_S16_LE;
				break;
			case AUDIO_S16MSB:
				format = SND_PCM_FORMAT_S16_BE;
				break;
			case AUDIO_U16LSB:
				format = SND_PCM_FORMAT_U16_LE;
				break;
			case AUDIO_U16MSB:
				format = SND_PCM_FORMAT_U16_BE;
				break;
			default:
				format = 0;
				break;
		}
		if ( format != 0 ) {
			status = SDL_NAME(snd_pcm_hw_params_set_format)(pcm_handle, hwparams, format);
		}
		if ( status < 0 ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	if ( status < 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		ALSA_CloseAudio(this);
		return(-1);
	}
	spec->format = test_format;

	/* Set the number of channels */
	status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels);
	if ( status < 0 ) {
		status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams);
		if ( (status <= 0) || (status > 2) ) {
			SDL_SetError("Couldn't set audio channels");
			ALSA_CloseAudio(this);
			return(-1);
		}
		spec->channels = status;
	}

	/* Set the audio rate */
	status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, spec->freq, NULL);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}
	spec->freq = status;

	/* Set the buffer size, in samples */
	frames = spec->samples;
	frames = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, frames, NULL);
	spec->samples = frames;
	SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, 2, NULL);

	/* "set" the hardware with the desired parameters */
	status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}

/* This is useful for debugging... */
/*
{ snd_pcm_sframes_t bufsize; int fragments;
   bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams);
   fragments = SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams);

   fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments);
}
*/

	/* Set the software parameters */
	snd_pcm_sw_params_alloca(&swparams);
	status = SDL_NAME(snd_pcm_sw_params_current)(pcm_handle, swparams);
	if ( status < 0 ) {
		SDL_SetError("Couldn't get software config: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}
	status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 0);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}
	status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, frames);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set avail min: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}
	status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams);
	if ( status < 0 ) {
		SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status));
		ALSA_CloseAudio(this);
		return(-1);
	}

	/* Calculate the final parameters for this audio specification */
	SDL_CalculateAudioSpec(spec);

	/* Allocate mixing buffer */
	mixlen = spec->size;
	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
	if ( mixbuf == NULL ) {
		ALSA_CloseAudio(this);
		return(-1);
	}
	SDL_memset(mixbuf, spec->silence, spec->size);

	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* Switch to blocking mode for playback */
	SDL_NAME(snd_pcm_nonblock)(pcm_handle, 0);

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #17
0
static int ARTSC_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int bits, frag_spec;
	Uint16 test_format, format;

	/* Reset the timer synchronization flag */
	frame_ticks = 0.0;

	mixbuf = NULL;

	/* Try for a closest match on audio format */
	format = 0;
	bits = 0;
	for ( test_format = SDL_FirstAudioFormat(spec->format);
						! format && test_format; ) {
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
		switch ( test_format ) {
			case AUDIO_U8:
				bits = 8;
				format = 1;
				break;
			case AUDIO_S16LSB:
				bits = 16;
				format = 1;
				break;
			default:
				format = 0;
				break;
		}
		if ( ! format ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	if ( format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	spec->format = test_format;

	stream = arts_play_stream(spec->freq, bits, spec->channels, "SDL");

	/* Calculate the final parameters for this audio specification */
	SDL_CalculateAudioSpec(spec);

	/* Determine the power of two of the fragment size */
	for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec );
	if ( (0x01<<frag_spec) != spec->size ) {
		SDL_SetError("Fragment size must be a power of two");
		return(-1);
	}
	frag_spec |= 0x00020000;	/* two fragments, for low latency */

#ifdef ARTS_P_PACKET_SETTINGS
	arts_stream_set(stream, ARTS_P_PACKET_SETTINGS, frag_spec);
#else
	arts_stream_set(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff);
	arts_stream_set(stream, ARTS_P_PACKET_COUNT, frag_spec>>16);
#endif
	spec->size = arts_stream_get(stream, ARTS_P_PACKET_SIZE);

	/* Allocate mixing buffer */
	mixlen = spec->size;
	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
	if ( mixbuf == NULL ) {
		return(-1);
	}
	memset(mixbuf, spec->silence, spec->size);

	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #18
0
static int
DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
    int format;
    int value;
    int frag_spec;
    SDL_AudioFormat test_format;

    /* We don't care what the devname is...we'll try to open anything. */
    /*  ...but default to first name in the list... */
    if (devname == NULL) {
        devname = SDL_GetAudioDeviceName(0, iscapture);
        if (devname == NULL) {
            return SDL_SetError("No such audio device");
        }
    }

    /* Make sure fragment size stays a power of 2, or OSS fails. */
    /* I don't know which of these are actually legal values, though... */
    if (this->spec.channels > 8)
        this->spec.channels = 8;
    else if (this->spec.channels > 4)
        this->spec.channels = 4;
    else if (this->spec.channels > 2)
        this->spec.channels = 2;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_zerop(this->hidden);

    /* Open the audio device */
    this->hidden->audio_fd = open(devname, flags, 0);
    if (this->hidden->audio_fd < 0) {
        return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
    }

    /* Make the file descriptor use blocking i/o with fcntl() */
    {
        long ctlflags;
        ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
        ctlflags &= ~O_NONBLOCK;
        if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
            return SDL_SetError("Couldn't set audio blocking mode");
        }
    }

    /* Get a list of supported hardware formats */
    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
        perror("SNDCTL_DSP_GETFMTS");
        return SDL_SetError("Couldn't get audio format list");
    }

    /* Try for a closest match on audio format */
    format = 0;
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !format && test_format;) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        switch (test_format) {
        case AUDIO_U8:
            if (value & AFMT_U8) {
                format = AFMT_U8;
            }
            break;
        case AUDIO_S16LSB:
            if (value & AFMT_S16_LE) {
                format = AFMT_S16_LE;
            }
            break;
        case AUDIO_S16MSB:
            if (value & AFMT_S16_BE) {
                format = AFMT_S16_BE;
            }
            break;
#if 0
/*
 * These formats are not used by any real life systems so they are not
 * needed here.
 */
        case AUDIO_S8:
            if (value & AFMT_S8) {
                format = AFMT_S8;
            }
            break;
        case AUDIO_U16LSB:
            if (value & AFMT_U16_LE) {
                format = AFMT_U16_LE;
            }
            break;
        case AUDIO_U16MSB:
            if (value & AFMT_U16_BE) {
                format = AFMT_U16_BE;
            }
            break;
#endif
        default:
            format = 0;
            break;
        }
        if (!format) {
            test_format = SDL_NextAudioFormat();
        }
    }
    if (format == 0) {
        return SDL_SetError("Couldn't find any hardware audio formats");
    }
    this->spec.format = test_format;

    /* Set the audio format */
    value = format;
    if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
        (value != format)) {
        perror("SNDCTL_DSP_SETFMT");
        return SDL_SetError("Couldn't set audio format");
    }

    /* Set the number of channels of output */
    value = this->spec.channels;
    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
        perror("SNDCTL_DSP_CHANNELS");
        return SDL_SetError("Cannot set the number of channels");
    }
    this->spec.channels = value;

    /* Set the DSP frequency */
    value = this->spec.freq;
    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
        perror("SNDCTL_DSP_SPEED");
        return SDL_SetError("Couldn't set audio frequency");
    }
    this->spec.freq = value;

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    /* Determine the power of two of the fragment size */
    for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
    if ((0x01U << frag_spec) != this->spec.size) {
        return SDL_SetError("Fragment size must be a power of two");
    }
    frag_spec |= 0x00020000;    /* two fragments, for low latency */

    /* Set the audio buffering parameters */
#ifdef DEBUG_AUDIO
    fprintf(stderr, "Requesting %d fragments of size %d\n",
            (frag_spec >> 16), 1 << (frag_spec & 0xFFFF));
#endif
    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
        perror("SNDCTL_DSP_SETFRAGMENT");
    }
#ifdef DEBUG_AUDIO
    {
        audio_buf_info info;
        ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETOSPACE, &info);
        fprintf(stderr, "fragments = %d\n", info.fragments);
        fprintf(stderr, "fragstotal = %d\n", info.fragstotal);
        fprintf(stderr, "fragsize = %d\n", info.fragsize);
        fprintf(stderr, "bytes = %d\n", info.bytes);
    }
#endif

    /* Allocate mixing buffer */
    if (!iscapture) {
        this->hidden->mixlen = this->spec.size;
        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
        if (this->hidden->mixbuf == NULL) {
            return SDL_OutOfMemory();
        }
        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
    }

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #19
0
static int
MME_OpenDevice(_THIS, const char *devname, int iscapture)
{
    int valid_format = 0;
    MMRESULT result;
    Uint8 *mixbuf = NULL;
    int i;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Set basic WAVE format parameters */
    this->hidden->shm = mmeAllocMem(sizeof(*this->hidden->shm));
    if (this->hidden->shm == NULL) {
        MME_CloseDevice(this);
        SDL_OutOfMemory();
        return 0;
    }

    SDL_memset(this->hidden->shm, '\0', sizeof(*this->hidden->shm));
    this->hidden->shm->sound = 0;
    this->hidden->shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;

    /* Determine the audio parameters from the AudioSpec */
    /* Try for a closest match on audio format */
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !valid_format && test_format;) {
        valid_format = 1;
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
            break;
        default:
            valid_format = 0;
            test_format = SDL_NextAudioFormat();
        }
    }

    if (!valid_format) {
        MME_CloseDevice(this);
        SDL_SetError("Unsupported audio format");
        return 0;
    }

    this->spec.format = test_format;
    this->hidden->shm->wFmt.wBitsPerSample = SDL_AUDIO_BITSIZE(test_format);

    /* !!! FIXME: Can this handle more than stereo? */
    this->hidden->shm->wFmt.wf.nChannels = this->spec.channels;
    this->hidden->shm->wFmt.wf.nSamplesPerSec = this->spec.freq;
    this->hidden->shm->wFmt.wf.nBlockAlign =
        this->hidden->shm->wFmt.wf.nChannels *
        this->hidden->shm->wFmt.wBitsPerSample / 8;
    this->hidden->shm->wFmt.wf.nAvgBytesPerSec =
        this->hidden->shm->wFmt.wf.nSamplesPerSec *
        this->hidden->shm->wFmt.wf.nBlockAlign;

    /* Check the buffer size -- minimum of 1/4 second (word aligned) */
    if (this->spec.samples < (this->spec.freq / 4))
        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* Open the audio device */
    result = waveOutOpen(&(this->hidden->shm->sound),
                         WAVE_MAPPER,
                         &(this->hidden->shm->wFmt.wf),
                         MME_Callback,
                         NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE));
    if (result != MMSYSERR_NOERROR) {
        MME_CloseDevice(this);
        SetMMerror("waveOutOpen()", result);
        return 0;
    }

    /* Create the sound buffers */
    mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (this->spec.size));
    if (mixbuf == NULL) {
        MME_CloseDevice(this);
        SDL_OutOfMemory();
        return 0;
    }
    this->hidden->mixbuf = mixbuf;

    for (i = 0; i < NUM_BUFFERS; i++) {
        this->hidden->shm->wHdr[i].lpData = &mixbuf[i * (this->spec.size)];
        this->hidden->shm->wHdr[i].dwBufferLength = this->spec.size;
        this->hidden->shm->wHdr[i].dwFlags = 0;
        this->hidden->shm->wHdr[i].dwUser = i;
        this->hidden->shm->wHdr[i].dwLoops = 0; /* loop control counter */
        this->hidden->shm->wHdr[i].lpNext = NULL;       /* reserved for driver */
        this->hidden->shm->wHdr[i].reserved = 0;
        inUse[i] = FALSE;
    }
    this->hidden->next_buffer = 0;

    return 1;
}
Пример #20
0
static int
SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    struct sio_par par;
    int status;

    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc(sizeof(*this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, sizeof(*this->hidden));

    this->hidden->mixlen = this->spec.size;

    /* !!! FIXME: SIO_DEVANY can be a specific device... */
    if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sio_open() failed");
    }

    SNDIO_sio_initpar(&par);

    par.rate = this->spec.freq;
    par.pchan = this->spec.channels;
    par.round = this->spec.samples;
    par.appbufsz = par.round * 2;

    /* Try for a closest match on audio format */
    status = -1;
    while (test_format && (status < 0)) {
        if (!SDL_AUDIO_ISFLOAT(test_format)) {
            par.le = SDL_AUDIO_ISLITTLEENDIAN(test_format) ? 1 : 0;
            par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
            par.bits = SDL_AUDIO_BITSIZE(test_format);

            if (SNDIO_sio_setpar(this->hidden->dev, &par) == 0) {
                continue;
            }
            if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
                SNDIO_CloseDevice(this);
                return SDL_SetError("sio_getpar() failed");
            }
            if (par.bps != SIO_BPS(par.bits)) {
                continue;
            }
            if ((par.bits == 8 * par.bps) || (par.msb)) {
                status = 0;
                break;
            }
        }
        test_format = SDL_NextAudioFormat();
    }

    if (status < 0) {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sndio: Couldn't find any hardware audio formats");
    }

    if ((par.bps == 4) && (par.sig) && (par.le))
        this->spec.format = AUDIO_S32LSB;
    else if ((par.bps == 4) && (par.sig) && (!par.le))
        this->spec.format = AUDIO_S32MSB;
    else if ((par.bps == 2) && (par.sig) && (par.le))
        this->spec.format = AUDIO_S16LSB;
    else if ((par.bps == 2) && (par.sig) && (!par.le))
        this->spec.format = AUDIO_S16MSB;
    else if ((par.bps == 2) && (!par.sig) && (par.le))
        this->spec.format = AUDIO_U16LSB;
    else if ((par.bps == 2) && (!par.sig) && (!par.le))
        this->spec.format = AUDIO_U16MSB;
    else if ((par.bps == 1) && (par.sig))
        this->spec.format = AUDIO_S8;
    else if ((par.bps == 1) && (!par.sig))
        this->spec.format = AUDIO_U8;
    else {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sndio: Got unsupported hardware audio format.");
    }

    this->spec.freq = par.rate;
    this->spec.channels = par.pchan;
    this->spec.samples = par.round;

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        SNDIO_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);

    if (!SNDIO_sio_start(this->hidden->dev)) {
        return SDL_SetError("sio_start() failed");
    }

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #21
0
static int
XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    HRESULT result = S_OK;
    WAVEFORMATEX waveformat;
    int valid_format = 0;
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    IXAudio2 *ixa2 = NULL;
    IXAudio2SourceVoice *source = NULL;
#if defined(SDL_XAUDIO2_WIN8)
    LPCWSTR devId = NULL;
#else
    UINT32 devId = 0;  /* 0 == system default device. */
#endif

    static IXAudio2VoiceCallbackVtbl callbacks_vtable = {
        VoiceCBOnVoiceProcessPassStart,
        VoiceCBOnVoiceProcessPassEnd,
        VoiceCBOnStreamEnd,
        VoiceCBOnBufferStart,
        VoiceCBOnBufferEnd,
        VoiceCBOnLoopEnd,
        VoiceCBOnVoiceError
    };

    static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };

#if defined(SDL_XAUDIO2_WIN8)
    /* !!! FIXME: hook up hotplugging. */
#else
    if (handle != NULL) {  /* specific device requested? */
        /* -1 because we increment the original value to avoid NULL. */
        const size_t val = ((size_t) handle) - 1;
        devId = (UINT32) val;
    }
#endif

    if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
        return SDL_SetError("XAudio2: XAudio2Create() failed at open.");
    }

    /*
    XAUDIO2_DEBUG_CONFIGURATION debugConfig;
    debugConfig.TraceMask = XAUDIO2_LOG_ERRORS; //XAUDIO2_LOG_WARNINGS | XAUDIO2_LOG_DETAIL | XAUDIO2_LOG_FUNC_CALLS | XAUDIO2_LOG_TIMING | XAUDIO2_LOG_LOCKS | XAUDIO2_LOG_MEMORY | XAUDIO2_LOG_STREAMING;
    debugConfig.BreakMask = XAUDIO2_LOG_ERRORS; //XAUDIO2_LOG_WARNINGS;
    debugConfig.LogThreadID = TRUE;
    debugConfig.LogFileline = TRUE;
    debugConfig.LogFunctionName = TRUE;
    debugConfig.LogTiming = TRUE;
    ixa2->SetDebugConfiguration(&debugConfig);
    */

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        IXAudio2_Release(ixa2);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    this->hidden->ixa2 = ixa2;
    this->hidden->semaphore = SDL_CreateSemaphore(1);
    if (this->hidden->semaphore == NULL) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: CreateSemaphore() failed!");
    }

    while ((!valid_format) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            this->spec.format = test_format;
            valid_format = 1;
            break;
        }
        test_format = SDL_NextAudioFormat();
    }

    if (!valid_format) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: Unsupported audio format");
    }

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* We feed a Source, it feeds the Mastering, which feeds the device. */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        XAUDIO2_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    this->hidden->nextbuf = this->hidden->mixbuf;
    SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen);

    /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On
       Xbox360, this means 5.1 output, but on Windows, it means "figure out
       what the system has." It might be preferable to let XAudio2 blast
       stereo output to appropriate surround sound configurations
       instead of clamping to 2 channels, even though we'll configure the
       Source Voice for whatever number of channels you supply. */
#if SDL_XAUDIO2_WIN8
    result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering,
                                           XAUDIO2_DEFAULT_CHANNELS,
                                           this->spec.freq, 0, devId, NULL, AudioCategory_GameEffects);
#else
    result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering,
                                           XAUDIO2_DEFAULT_CHANNELS,
                                           this->spec.freq, 0, devId, NULL);
#endif
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: Couldn't create mastering voice");
    }

    SDL_zero(waveformat);
    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
        waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    } else {
        waveformat.wFormatTag = WAVE_FORMAT_PCM;
    }
    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
    waveformat.nChannels = this->spec.channels;
    waveformat.nSamplesPerSec = this->spec.freq;
    waveformat.nBlockAlign =
        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
    waveformat.nAvgBytesPerSec =
        waveformat.nSamplesPerSec * waveformat.nBlockAlign;
    waveformat.cbSize = sizeof(waveformat);

#ifdef __WINRT__
    // DLudwig: for now, make XAudio2 do sample rate conversion, just to
    // get the loopwave test to work.
    //
    // TODO, WinRT: consider removing WinRT-specific source-voice creation code from SDL_xaudio2.c
    result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat,
                                        0,
                                        1.0f, &callbacks, NULL, NULL);
#else
    result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat,
                                        XAUDIO2_VOICE_NOSRC |
                                        XAUDIO2_VOICE_NOPITCH,
                                        1.0f, &callbacks, NULL, NULL);

#endif
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: Couldn't create source voice");
    }
    this->hidden->source = source;

    /* Start everything playing! */
    result = IXAudio2_StartEngine(ixa2);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: Couldn't start engine");
    }

    result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
    if (result != S_OK) {
        XAUDIO2_CloseDevice(this);
        return SDL_SetError("XAudio2: Couldn't start source voice");
    }

    return 0; /* good to go. */
}
Пример #22
0
static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int             state;
	Uint16          test_format;
	pa_sample_spec  paspec;
	pa_buffer_attr  paattr;
	pa_channel_map  pacmap;
	pa_stream_flags_t flags = 0;

	paspec.format = PA_SAMPLE_INVALID;
	for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) {
		switch ( test_format ) {
			case AUDIO_U8:
				paspec.format = PA_SAMPLE_U8;
				break;
			case AUDIO_S16LSB:
				paspec.format = PA_SAMPLE_S16LE;
				break;
			case AUDIO_S16MSB:
				paspec.format = PA_SAMPLE_S16BE;
				break;
		}
		if ( paspec.format != PA_SAMPLE_INVALID )
			break;
		test_format = SDL_NextAudioFormat();
	}
	if (paspec.format == PA_SAMPLE_INVALID ) {
		SDL_SetError("Couldn't find any suitable audio formats");
		return(-1);
	}
	spec->format = test_format;

	paspec.channels = spec->channels;
	paspec.rate = spec->freq;

	
#ifdef PA_STREAM_ADJUST_LATENCY
	spec->samples /= 2; 
#endif
	SDL_CalculateAudioSpec(spec);

	
	mixlen = spec->size;
	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
	if ( mixbuf == NULL ) {
		return(-1);
	}
	SDL_memset(mixbuf, spec->silence, spec->size);

	
#ifdef PA_STREAM_ADJUST_LATENCY
	paattr.tlength = mixlen * 4; 
	paattr.prebuf = -1;
	paattr.maxlength = -1;
	paattr.minreq = mixlen; 
	flags = PA_STREAM_ADJUST_LATENCY;
#else
	paattr.tlength = mixlen*2;
	paattr.prebuf = mixlen*2;
	paattr.maxlength = mixlen*2;
	paattr.minreq = mixlen;
#endif

	
	
	SDL_NAME(pa_channel_map_init_auto)(
		&pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX);

	
	if (!(mainloop = SDL_NAME(pa_mainloop_new)())) {
		PULSE_CloseAudio(this);
		SDL_SetError("pa_mainloop_new() failed");
		return(-1);
	}

	if (this->hidden->caption == NULL) {
		char *title = NULL;
		SDL_WM_GetCaption(&title, NULL);
		PULSE_SetCaption(this, title);
	}

	mainloop_api = SDL_NAME(pa_mainloop_get_api)(mainloop);
	if (!(context = SDL_NAME(pa_context_new)(mainloop_api,
	                                         this->hidden->caption))) {
		PULSE_CloseAudio(this);
		SDL_SetError("pa_context_new() failed");
		return(-1);
	}

	
	if (SDL_NAME(pa_context_connect)(context, NULL, 0, NULL) < 0) {
		PULSE_CloseAudio(this);
		SDL_SetError("Could not setup connection to PulseAudio");
		return(-1);
	}

	do {
		if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) {
			PULSE_CloseAudio(this);
			SDL_SetError("pa_mainloop_iterate() failed");
			return(-1);
		}
		state = SDL_NAME(pa_context_get_state)(context);
		if (!PA_CONTEXT_IS_GOOD(state)) {
			PULSE_CloseAudio(this);
			SDL_SetError("Could not connect to PulseAudio");
			return(-1);
		}
	} while (state != PA_CONTEXT_READY);

	stream = SDL_NAME(pa_stream_new)(
		context,
		"Simple DirectMedia Layer",  
		&paspec,                     
		&pacmap                      
	);
	if ( stream == NULL ) {
		PULSE_CloseAudio(this);
		SDL_SetError("Could not setup PulseAudio stream");
		return(-1);
	}

	if (SDL_NAME(pa_stream_connect_playback)(stream, NULL, &paattr, flags,
			NULL, NULL) < 0) {
		PULSE_CloseAudio(this);
		SDL_SetError("Could not connect PulseAudio stream");
		return(-1);
	}

	do {
		if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) {
			PULSE_CloseAudio(this);
			SDL_SetError("pa_mainloop_iterate() failed");
			return(-1);
		}
		state = SDL_NAME(pa_stream_get_state)(stream);
		if (!PA_STREAM_IS_GOOD(state)) {
			PULSE_CloseAudio(this);
			SDL_SetError("Could not create to PulseAudio stream");
			return(-1);
		}
	} while (state != PA_STREAM_READY);

	return(0);
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
	long snd_format = 0;
	int i, resolution, format_signed, format_bigendian;
    Uint16 test_format = SDL_FirstAudioFormat(spec->format);
    int valid_datatype = 0;

	resolution = spec->format & 0x00ff;
	format_signed = ((spec->format & 0x8000)!=0);
	format_bigendian = ((spec->format & 0x1000)!=0);

	DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
	DEBUG_PRINT(("channels=%d, ", spec->channels));
	DEBUG_PRINT(("freq=%d\n", spec->freq));

    if (spec->channels > 2) {
        spec->channels = 2;  
    }

    while ((!valid_datatype) && (test_format)) {
        
        snd_format = Sndstatus(SND_QUERYFORMATS);
        spec->format = test_format;
        resolution = spec->format & 0xff;
        format_signed = (spec->format & (1<<15));
        format_bigendian = (spec->format & (1<<12));
        switch (test_format) {
            case AUDIO_U8:
            case AUDIO_S8:
                if (snd_format & SND_FORMAT8) {
                    valid_datatype = 1;
                    snd_format = Sndstatus(SND_QUERY8BIT);
                }
                break;

            case AUDIO_U16LSB:
            case AUDIO_S16LSB:
            case AUDIO_U16MSB:
            case AUDIO_S16MSB:
                if (snd_format & SND_FORMAT16) {
                    valid_datatype = 1;
                    snd_format = Sndstatus(SND_QUERY16BIT);
                }
                break;

            default:
                test_format = SDL_NextAudioFormat();
                break;
        }
    }

    if (!valid_datatype) {
        SDL_SetError("Unsupported audio format");
        return (-1);
    }

	
	if (format_signed) {
		if (snd_format & SND_FORMATSIGNED) {
			
		} else if (snd_format & SND_FORMATUNSIGNED) {
			
			spec->format = spec->format & (~0x8000);
		}
	} else {
		if (snd_format & SND_FORMATUNSIGNED) {
			
		} else if (snd_format & SND_FORMATSIGNED) {
			
			spec->format |= 0x8000;
		}
	}

	if (format_bigendian) {
		if (snd_format & SND_FORMATBIGENDIAN) {
			
		} else if (snd_format & SND_FORMATLITTLEENDIAN) {
			
			spec->format = spec->format & (~0x1000);
		}
	} else {
		if (snd_format & SND_FORMATLITTLEENDIAN) {
			
		} else if (snd_format & SND_FORMATBIGENDIAN) {
			
			spec->format |= 0x1000;
		}
	}
	
	
	MINTAUDIO_freqcount=0;
	for (i=1;i<4;i++) {
		SDL_MintAudio_AddFrequency(this,
			MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(1<<i)), MASTERCLOCK_44K,
			(1<<i)-1, -1);
	}

#if 1
	for (i=0; i<MINTAUDIO_freqcount; i++) {
		DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
			i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
			MINTAUDIO_frequencies[i].predivisor
		));
	}
#endif

	MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
	spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;

	DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
	DEBUG_PRINT(("channels=%d, ", spec->channels));
	DEBUG_PRINT(("freq=%d\n", spec->freq));

	return 0;
}
Пример #24
0
static int
DART_OpenDevice(_THIS, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
    int valid_datatype = 0;
    MCI_AMP_OPEN_PARMS AmpOpenParms;
    int iDeviceOrd = 0;         // Default device to be used
    int bOpenShared = 1;        // Try opening it shared
    int iBits = 16;             // Default is 16 bits signed
    int iFreq = 44100;          // Default is 44KHz
    int iChannels = 2;          // Default is 2 channels (Stereo)
    int iNumBufs = 2;           // Number of audio buffers: 2
    int iBufSize;
    int iOpenMode;
    int iSilence;
    int rc;

    /* Initialize all variables that we clean on shutdown */
    _this->hidden = (struct SDL_PrivateAudioData *)
                    SDL_malloc((sizeof *_this->hidden));
    if (_this->hidden == NULL) {
        SDL_OutOfMemory();
        return 0;
    }
    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));

    // First thing is to try to open a given DART device!
    SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
    // pszDeviceType should contain the device type in low word, and device ordinal in high word!
    AmpOpenParms.pszDeviceType =
        (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16));

    iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID;
    if (bOpenShared)
        iOpenMode |= MCI_OPEN_SHAREABLE;

    rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0);
    if (rc != MCIERR_SUCCESS) { // No audio available??
        DART_CloseDevice(_this);
        SDL_SetError("DART: Couldn't open audio device.");
        return 0;
    }
    // Save the device ID we got from DART!
    // We will use this in the next calls!
    _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID;

    // Determine the audio parameters from the AudioSpec
    if (_this->spec.channels > 4)
        _this->spec.channels = 4;

    while ((!valid_datatype) && (test_format)) {
        _this->spec.format = test_format;
        valid_datatype = 1;
        switch (test_format) {
        case AUDIO_U8:
            // Unsigned 8 bit audio data
            iSilence = 0x80;
            _this->hidden->iCurrBits = iBits = 8;
            break;

        case AUDIO_S16LSB:
            // Signed 16 bit audio data
            iSilence = 0x00;
            _this->hidden->iCurrBits = iBits = 16;
            break;

        // !!! FIXME: int32?

        default:
            valid_datatype = 0;
            test_format = SDL_NextAudioFormat();
            break;
        }
    }

    if (!valid_datatype) {      // shouldn't happen, but just in case...
        // Close DART, and exit with error code!
        DART_CloseDevice(_this);
        SDL_SetError("Unsupported audio format");
        return 0;
    }

    _this->hidden->iCurrFreq = iFreq = _this->spec.freq;
    _this->hidden->iCurrChannels = iChannels = _this->spec.channels;
    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&_this->spec);
    _this->hidden->iCurrBufSize = iBufSize = _this->spec.size;

    // Now query this device if it supports the given freq/bits/channels!
    SDL_memset(&(_this->hidden->MixSetupParms), 0,
               sizeof(MCI_MIXSETUP_PARMS));
    _this->hidden->MixSetupParms.ulBitsPerSample = iBits;
    _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
    _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq;
    _this->hidden->MixSetupParms.ulChannels = iChannels;
    _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY;
    _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
    _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc;
    rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
                        MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
                        &(_this->hidden->MixSetupParms), 0);
    if (rc != MCIERR_SUCCESS) { // The device cannot handle this format!
        // Close DART, and exit with error code!
        DART_CloseDevice(_this);
        SDL_SetError("Audio device doesn't support requested audio format");
        return 0;
    }
    // The device can handle this format, so initialize!
    rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
                        MCI_WAIT | MCI_MIXSETUP_INIT,
                        &(_this->hidden->MixSetupParms), 0);
    if (rc != MCIERR_SUCCESS) { // The device could not be opened!
        // Close DART, and exit with error code!
        DART_CloseDevice(_this);
        SDL_SetError("Audio device could not be set up");
        return 0;
    }
    // Ok, the device is initialized.
    // Now we should allocate buffers. For this, we need a place where
    // the buffer descriptors will be:
    _this->hidden->pMixBuffers =
        (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs);
    if (!(_this->hidden->pMixBuffers)) {        // Not enough memory!
        // Close DART, and exit with error code!
        DART_CloseDevice(_this);
        SDL_OutOfMemory();
        return 0;
    }
    // Now that we have the place for buffer list, we can ask DART for the
    // buffers!
    _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers
    _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size
    _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers;   // getting descriptorts into this list
    // Allocate buffers!
    rc = mciSendCommand(iDeviceOrd, MCI_BUFFER,
                        MCI_WAIT | MCI_ALLOCATE_MEMORY,
                        &(_this->hidden->BufferParms), 0);
    if ((rc != MCIERR_SUCCESS)
            || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers)
            || (_this->hidden->BufferParms.ulBufferSize == 0)) {    // Could not allocate memory!
        // Close DART, and exit with error code!
        DART_CloseDevice(_this);
        SDL_SetError("DART could not allocate buffers");
        return 0;
    }
    _this->hidden->iCurrNumBufs = iNumBufs;

    // Ok, we have all the buffers allocated, let's mark them!
    {
        int i;
        for (i = 0; i < iNumBufs; i++) {
            pMixBufferDesc pBufferDesc =
                (pMixBufferDesc) SDL_malloc(sizeof(tMixBufferDesc));;
            // Check if this buffer was really allocated by DART
            if ((!(_this->hidden->pMixBuffers[i].pBuffer))
                    || (!pBufferDesc)) {    // Wrong buffer!
                DART_CloseDevice(_this);
                SDL_SetError("Error at internal buffer check");
                return 0;
            }
            pBufferDesc->iBufferUsage = BUFFER_EMPTY;
            pBufferDesc->pSDLAudioDevice = _this;

            _this->hidden->pMixBuffers[i].ulBufferLength =
                _this->hidden->BufferParms.ulBufferSize;
            _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc;     // User parameter: Description of buffer
            _this->hidden->pMixBuffers[i].ulFlags = 0;  // Some stuff should be flagged here for DART, like end of
            // audio data, but as we will continously send
            // audio data, there will be no end.:)
            SDL_memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence,
                       iBufSize);
        }
    }
    _this->hidden->iNextFreeBuffer = 0;
    _this->hidden->iLastPlayedBuf = -1;
    // Create event semaphore
    if (DosCreateEventSem
            (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR)
    {
        DART_CloseDevice(_this);
        SDL_SetError("Could not create event semaphore");
        return 0;
    }

    return 1;
}
Пример #25
0
static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
    char*  audiodev = "/dev/paud0";
    long   lgain;
    long   rgain;
    long   outRate;
    long   outBufSize;
    long   bitsPerSample;
    long   samplesPerSec;
    long   success;
    Uint16 test_format;
    int    frag_spec;
    UMSAudioDevice_ReturnCode rc;

#ifdef DEBUG_AUDIO
    fprintf(stderr, "enter UMS_OpenAudio\n");
#endif
    rc = UADOpen(this, audiodev,"PLAY", UMSAudioDevice_BlockingIO);
    if ( rc != UMSAudioDevice_Success ) {
	SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
	return -1;
    }
 
    rc = UADSetAudioFormatType(this, "PCM"); 

    success = 0;
    test_format = SDL_FirstAudioFormat(spec->format);
    do
    {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        switch ( test_format )
        {
        case AUDIO_U8:
/* from the mac code: better ? */
/* sample_bits = spec->size / spec->samples / spec->channels * 8; */
	    success       = 1;
            bitsPerSample = 8;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "MSB");       /* irrelevant */
            rc = UADSetNumberFormat(this, "UNSIGNED");
            break;
        case AUDIO_S8:
	    success       = 1;
            bitsPerSample = 8;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "MSB");       /* irrelevant */
            rc = UADSetNumberFormat(this, "SIGNED");
            break;
        case AUDIO_S16LSB:
	    success       = 1;
            bitsPerSample = 16;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "LSB");
            rc = UADSetNumberFormat(this, "SIGNED");
            break;
        case AUDIO_S16MSB:
	    success       = 1;
            bitsPerSample = 16;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "MSB");
            rc = UADSetNumberFormat(this, "SIGNED");
            break;
        case AUDIO_U16LSB:
	    success       = 1;
            bitsPerSample = 16;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "LSB");
            rc = UADSetNumberFormat(this, "UNSIGNED");
            break;
        case AUDIO_U16MSB:
	    success       = 1;
            bitsPerSample = 16;
            rc = UADSetSampleRate(this,  spec->freq << 16, &outRate );
            rc = UADSetByteOrder(this, "MSB");
            rc = UADSetNumberFormat(this, "UNSIGNED");
            break;
        default:
            break;
        }
        if ( ! success ) {
            test_format = SDL_NextAudioFormat();
        }
    }
    while ( ! success && test_format );

    if ( success == 0 ) {
        SDL_SetError("Couldn't find any hardware audio formats");
        return -1;
    }

    spec->format = test_format;

    for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec );
    if ( (0x01<<frag_spec) != spec->size ) {
        SDL_SetError("Fragment size must be a power of two");
        return -1;
    }
    if ( frag_spec > 2048 ) frag_spec = 2048;

    this->hidden->bytesPerSample   = (bitsPerSample / 8) * spec->channels;
    samplesPerSec                  = this->hidden->bytesPerSample * outRate;

    this->hidden->playbuf._length  = 0;
    this->hidden->playbuf._maximum = spec->size;
    this->hidden->playbuf._buffer  = (unsigned char*)malloc(spec->size);
    this->hidden->fillbuf._length  = 0;
    this->hidden->fillbuf._maximum = spec->size;
    this->hidden->fillbuf._buffer  = (unsigned char*)malloc(spec->size);

    rc = UADSetBitsPerSample(this,  bitsPerSample );
    rc = UADSetDMABufferSize(this,  frag_spec, &outBufSize );
    rc = UADSetChannels(this, spec->channels);      /* functions reduces to mono or stereo */

    lgain = 100; /*maximum left input gain*/
    rgain = 100; /*maimum right input gain*/
    rc = UADEnableOutput(this, "LINE_OUT",&lgain,&rgain);
    rc = UADInitialize(this);
    rc = UADStart(this);
    rc = UADSetVolume(this, 100);
    rc = UADSetBalance(this, 0);

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #26
0
static int
PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
{
    const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
    char audiodev[1024];
    const char *err = NULL;
    int format;
    int bytes_per_sample;
    SDL_AudioFormat test_format;
    audio_init paud_init;
    audio_buffer paud_bufinfo;
    audio_status paud_status;
    audio_control paud_control;
    audio_change paud_change;
    int fd = -1;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Open the audio device */
    fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
    this->hidden->audio_fd = fd;
    if (fd < 0) {
        PAUDIO_CloseDevice(this);
        return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
    }

    /*
     * We can't set the buffer size - just ask the device for the maximum
     * that we can have.
     */
    if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
        PAUDIO_CloseDevice(this);
        return SDL_SetError("Couldn't get audio buffer information");
    }

    if (this->spec.channels > 1)
        this->spec.channels = 2;
    else
        this->spec.channels = 1;

    /*
     * Fields in the audio_init structure:
     *
     * Ignored by us:
     *
     * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only?
     * paud.slot_number;         * slot number of the adapter
     * paud.device_id;           * adapter identification number
     *
     * Input:
     *
     * paud.srate;           * the sampling rate in Hz
     * paud.bits_per_sample; * 8, 16, 32, ...
     * paud.bsize;           * block size for this rate
     * paud.mode;            * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX
     * paud.channels;        * 1=mono, 2=stereo
     * paud.flags;           * FIXED - fixed length data
     *                       * LEFT_ALIGNED, RIGHT_ALIGNED (var len only)
     *                       * TWOS_COMPLEMENT - 2's complement data
     *                       * SIGNED - signed? comment seems wrong in sys/audio.h
     *                       * BIG_ENDIAN
     * paud.operation;       * PLAY, RECORD
     *
     * Output:
     *
     * paud.flags;           * PITCH            - pitch is supported
     *                       * INPUT            - input is supported
     *                       * OUTPUT           - output is supported
     *                       * MONITOR          - monitor is supported
     *                       * VOLUME           - volume is supported
     *                       * VOLUME_DELAY     - volume delay is supported
     *                       * BALANCE          - balance is supported
     *                       * BALANCE_DELAY    - balance delay is supported
     *                       * TREBLE           - treble control is supported
     *                       * BASS             - bass control is supported
     *                       * BESTFIT_PROVIDED - best fit returned
     *                       * LOAD_CODE        - DSP load needed
     * paud.rc;              * NO_PLAY         - DSP code can't do play requests
     *                       * NO_RECORD       - DSP code can't do record requests
     *                       * INVALID_REQUEST - request was invalid
     *                       * CONFLICT        - conflict with open's flags
     *                       * OVERLOADED      - out of DSP MIPS or memory
     * paud.position_resolution; * smallest increment for position
     */

    paud_init.srate = this->spec.freq;
    paud_init.mode = PCM;
    paud_init.operation = PLAY;
    paud_init.channels = this->spec.channels;

    /* Try for a closest match on audio format */
    format = 0;
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !format && test_format;) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        switch (test_format) {
        case AUDIO_U8:
            bytes_per_sample = 1;
            paud_init.bits_per_sample = 8;
            paud_init.flags = TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        case AUDIO_S8:
            bytes_per_sample = 1;
            paud_init.bits_per_sample = 8;
            paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        case AUDIO_S16LSB:
            bytes_per_sample = 2;
            paud_init.bits_per_sample = 16;
            paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        case AUDIO_S16MSB:
            bytes_per_sample = 2;
            paud_init.bits_per_sample = 16;
            paud_init.flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        case AUDIO_U16LSB:
            bytes_per_sample = 2;
            paud_init.bits_per_sample = 16;
            paud_init.flags = TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        case AUDIO_U16MSB:
            bytes_per_sample = 2;
            paud_init.bits_per_sample = 16;
            paud_init.flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
            format = 1;
            break;
        default:
            break;
        }
        if (!format) {
            test_format = SDL_NextAudioFormat();
        }
    }
    if (format == 0) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Couldn't find any hardware audio formats\n");
#endif
        PAUDIO_CloseDevice(this);
        return SDL_SetError("Couldn't find any hardware audio formats");
    }
    this->spec.format = test_format;

    /*
     * We know the buffer size and the max number of subsequent writes
     *  that can be pending. If more than one can pend, allow the application
     *  to do something like double buffering between our write buffer and
     *  the device's own buffer that we are filling with write() anyway.
     *
     * We calculate this->spec.samples like this because
     *  SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap
     *  (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return.
     */
    if (paud_bufinfo.request_buf_cap == 1) {
        this->spec.samples = paud_bufinfo.write_buf_cap
            / bytes_per_sample / this->spec.channels;
    } else {
        this->spec.samples = paud_bufinfo.write_buf_cap
            / bytes_per_sample / this->spec.channels / 2;
    }
    paud_init.bsize = bytes_per_sample * this->spec.channels;

    SDL_CalculateAudioSpec(&this->spec);

    /*
     * The AIX paud device init can't modify the values of the audio_init
     * structure that we pass to it. So we don't need any recalculation
     * of this stuff and no reinit call as in linux dsp code.
     *
     * /dev/paud supports all of the encoding formats, so we don't need
     * to do anything like reopening the device, either.
     */
    if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) {
        switch (paud_init.rc) {
        case 1:
            err = "Couldn't set audio format: DSP can't do play requests";
            break;
        case 2:
            err = "Couldn't set audio format: DSP can't do record requests";
            break;
        case 4:
            err = "Couldn't set audio format: request was invalid";
            break;
        case 5:
            err = "Couldn't set audio format: conflict with open's flags";
            break;
        case 6:
            err = "Couldn't set audio format: out of DSP MIPS or memory";
            break;
        default:
            err = "Couldn't set audio format: not documented in sys/audio.h";
            break;
        }
    }

    if (err != NULL) {
        PAUDIO_CloseDevice(this);
        return SDL_SetError("Paudio: %s", err);
    }

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        PAUDIO_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

    /*
     * Set some paramters: full volume, first speaker that we can find.
     * Ignore the other settings for now.
     */
    paud_change.input = AUDIO_IGNORE;   /* the new input source */
    paud_change.output = OUTPUT_1;      /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */
    paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
    paud_change.volume = 0x7fffffff;    /* volume level [0-0x7fffffff] */
    paud_change.volume_delay = AUDIO_IGNORE;    /* the new volume delay */
    paud_change.balance = 0x3fffffff;   /* the new balance */
    paud_change.balance_delay = AUDIO_IGNORE;   /* the new balance delay */
    paud_change.treble = AUDIO_IGNORE;  /* the new treble state */
    paud_change.bass = AUDIO_IGNORE;    /* the new bass state */
    paud_change.pitch = AUDIO_IGNORE;   /* the new pitch state */

    paud_control.ioctl_request = AUDIO_CHANGE;
    paud_control.request_info = (char *) &paud_change;
    if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Can't change audio display settings\n");
#endif
    }

    /*
     * Tell the device to expect data. Actual start will wait for
     * the first write() call.
     */
    paud_control.ioctl_request = AUDIO_START;
    paud_control.position = 0;
    if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
        PAUDIO_CloseDevice(this);
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Can't start audio play\n");
#endif
        return SDL_SetError("Can't start audio play");
    }

    /* Check to see if we need to use select() workaround */
    if (workaround != NULL) {
        this->hidden->frame_ticks = (float) (this->spec.samples * 1000) /
            this->spec.freq;
        this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
    }

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #27
0
static int NTO_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	int rval;
	int format;
	Uint16 test_format;
	int twidth;
	int found;

#ifdef DEBUG_AUDIO
		fprintf(stderr, "NTO_OpenAudio\n");
#endif
	
	audio_handle = NULL;
	 this->enabled = 0;

	if ( pcm_buf != NULL ) {
		free((Uint8 *)pcm_buf); 
		pcm_buf = NULL;
	}
	 
	/* initialize channel transfer parameters to default */
	init_pcm_cparams(&cparams);

	/* Open the audio device */
	
	rval = snd_pcm_open_preferred(&audio_handle, &card_no, &device_no, OPEN_FLAGS);
	if ( rval < 0 ) {
		SDL_SetError("snd_pcm_open failed: %s\n", snd_strerror(rval));
		return(-1);
	}

    /* set to nonblocking mode */
    if ((rval = snd_pcm_nonblock_mode(audio_handle, 1))<0) //I assume 1 means on
    {
        SDL_SetError("snd_pcm_nonblock_mode failed: %s\n", snd_strerror(rval));
        return(-1);
    }

    /* enable count status parameter */
    if ((rval = snd_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP))<0)
    {
        SDL_SetError("snd_plugin_set_disable failed: %s\n", snd_strerror(rval));
        return(-1);
    }


	/* Try for a closest match on audio format */
	format = 0;
 	found = 0; // can't use format as SND_PCM_SFMT_U8 = 0 in nto
	for ( test_format = SDL_FirstAudioFormat(spec->format);	!found ; ) 

	{
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x spec->samples %d\n", test_format,spec->samples);
#endif
			/* if match found set format to equivalent ALSA format */
        switch ( test_format ) {
			case AUDIO_U8:
				format = SND_PCM_SFMT_U8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S8:
				format = SND_PCM_SFMT_S8;
				cparams.buf.block.frag_size = spec->samples * spec->channels;
				found = 1;
				break;
			case AUDIO_S16LSB:
				format = SND_PCM_SFMT_S16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_S16MSB:
				format = SND_PCM_SFMT_S16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16LSB:
				format = SND_PCM_SFMT_U16_LE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			case AUDIO_U16MSB:
				format = SND_PCM_SFMT_U16_BE;
				cparams.buf.block.frag_size = spec->samples*2 * spec->channels;
				found = 1;
				break;
			default:
				break;
		}
		if ( ! found ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	
	/* assumes test_format not 0 on success */
	if ( test_format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	
	spec->format = test_format;

	/* Set the audio format */
	cparams.format.format = format;

	/* Set mono or stereo audio (currently only two channels supported) */
	cparams.format.voices = spec->channels;
	
#ifdef DEBUG_AUDIO
	fprintf(stderr,"intializing channels %d\n", cparams.format.voices);
#endif

	
	/* Set rate */
	cparams.format.rate = spec->freq ;

	/* Setup the transfer parameters according to cparams */
	rval = snd_pcm_plugin_params(audio_handle, &cparams);
	if (rval < 0) {
		SDL_SetError("snd_pcm_channel_params failed: %s\n", snd_strerror (rval));
		return(-1);
	}

    /*  Make sure channel is setup right one last time */
    memset( &csetup, 0, sizeof( csetup ) );
    csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ( snd_pcm_plugin_setup( audio_handle, &csetup ) < 0 )
    {
        SDL_SetError("Unable to setup playback channel\n" );
        return(-1);
    }
    else
    {
#ifdef DEBUG_AUDIO
        fprintf(stderr,"requested format: %d\n",cparams.format.format);
        fprintf(stderr,"requested frag size: %d\n",cparams.buf.block.frag_size);
        fprintf(stderr,"requested max frags: %d\n\n",cparams.buf.block.frags_max);

        fprintf(stderr,"real format: %d\n", csetup.format.format );
        fprintf(stderr,"real frag size : %d\n", csetup.buf.block.frag_size );
		fprintf(stderr,"real max frags : %d\n", csetup.buf.block.frags_max );
#endif // DEBUG_AUDIO
    }


    /*  Allocate memory to the audio buffer and initialize with silence
        (Note that buffer size must be a multiple of fragment size, so find closest multiple)
    */
    
    twidth = snd_pcm_format_width(format);
    if (twidth < 0) {
        printf("snd_pcm_format_width failed\n");
        twidth = 0;
    }
    
#ifdef DEBUG_AUDIO
    fprintf(stderr,"format is %d bits wide\n",twidth);
#endif      
    
    pcm_len = spec->size ;
    
  
#ifdef DEBUG_AUDIO    
    fprintf(stderr,"pcm_len set to %d\n", pcm_len);
#endif
    
    if (pcm_len == 0)
    {
        pcm_len = csetup.buf.block.frag_size;
    }
    
    pcm_buf = (Uint8*)malloc(pcm_len);
    if (pcm_buf == NULL) {
        SDL_SetError("pcm_buf malloc failed\n");
        return(-1);
    }
    memset(pcm_buf,spec->silence,pcm_len);

#ifdef DEBUG_AUDIO
	fprintf(stderr,"pcm_buf malloced and silenced.\n");
#endif

    /* get the file descriptor */
    if( (audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
       fprintf(stderr, "snd_pcm_file_descriptor failed with error code: %d\n", audio_fd);
    }

	/* Trigger audio playback */
	rval = snd_pcm_plugin_prepare( audio_handle, SND_PCM_CHANNEL_PLAYBACK);
	if (rval < 0) {
       SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rval));
       return(-1);
	}
	
	 this->enabled = 1;
	 
	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #28
0
static int
NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    AuElement elms[3];
    int buffer_size;
    SDL_AudioFormat test_format, format;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));

    /* Try for a closest match on audio format */
    format = 0;
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !format && test_format;) {
        format = sdlformat_to_auformat(test_format);
        if (format == AuNone) {
            test_format = SDL_NextAudioFormat();
        }
    }
    if (format == 0) {
        NAS_CloseDevice(this);
        return SDL_SetError("NAS: Couldn't find any hardware audio formats");
    }
    this->spec.format = test_format;

    this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
    if (this->hidden->aud == 0) {
        NAS_CloseDevice(this);
        return SDL_SetError("NAS: Couldn't open connection to NAS server");
    }

    this->hidden->dev = find_device(this, this->spec.channels);
    if ((this->hidden->dev == AuNone)
        || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
        NAS_CloseDevice(this);
        return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
    }

    buffer_size = this->spec.freq;
    if (buffer_size < 4096)
        buffer_size = 4096;

    if (buffer_size > 32768)
        buffer_size = 32768;    /* So that the buffer won't get unmanageably big. */

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    this2 = this->hidden;

    AuMakeElementImportClient(elms, this->spec.freq, format,
                              this->spec.channels, AuTrue, buffer_size,
                              buffer_size / 4, 0, NULL);
    AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
                              AuUnlimitedSamples, 0, NULL);
    NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
                      NULL);
    NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
                               this->hidden->flow, event_handler,
                               (AuPointer) NULL);

    NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        NAS_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

    /* We're ready to rock and roll. :-) */
    return 0;
}
Пример #29
0
static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
	char audiodev[1024];
	int format;
	int stereo;
	int value;
	Uint16 test_format;
	struct audio_buf_info info;

	/* Reset the timer synchronization flag */
	frame_ticks = 0.0;

	/* Open the audio device */
	audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
	if ( audio_fd < 0 ) {
		SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
		return(-1);
	}
	dma_buf = NULL;
	ioctl(audio_fd, SNDCTL_DSP_RESET, 0);

	/* Get a list of supported hardware formats */
	if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) {
		SDL_SetError("Couldn't get audio format list");
		return(-1);
	}

	/* Try for a closest match on audio format */
	format = 0;
	for ( test_format = SDL_FirstAudioFormat(spec->format);
						! format && test_format; ) {
#ifdef DEBUG_AUDIO
		fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
		switch ( test_format ) {
			case AUDIO_U8:
				if ( value & AFMT_U8 ) {
					format = AFMT_U8;
				}
				break;
			case AUDIO_S8:
				if ( value & AFMT_S8 ) {
					format = AFMT_S8;
				}
				break;
			case AUDIO_S16LSB:
				if ( value & AFMT_S16_LE ) {
					format = AFMT_S16_LE;
				}
				break;
			case AUDIO_S16MSB:
				if ( value & AFMT_S16_BE ) {
					format = AFMT_S16_BE;
				}
				break;
			case AUDIO_U16LSB:
				if ( value & AFMT_U16_LE ) {
					format = AFMT_U16_LE;
				}
				break;
			case AUDIO_U16MSB:
				if ( value & AFMT_U16_BE ) {
					format = AFMT_U16_BE;
				}
				break;
			default:
				format = 0;
				break;
		}
		if ( ! format ) {
			test_format = SDL_NextAudioFormat();
		}
	}
	if ( format == 0 ) {
		SDL_SetError("Couldn't find any hardware audio formats");
		return(-1);
	}
	spec->format = test_format;

	/* Set the audio format */
	value = format;
	if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
						(value != format) ) {
		SDL_SetError("Couldn't set audio format");
		return(-1);
	}

	/* Set mono or stereo audio (currently only two channels supported) */
	stereo = (spec->channels > 1);
	ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
	if ( stereo ) {
		spec->channels = 2;
	} else {
		spec->channels = 1;
	}

	/* Because some drivers don't allow setting the buffer size
	   after setting the format, we must re-open the audio device
	   once we know what format and channels are supported
	 */
	if ( DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0 ) {
		/* Error is set by DMA_ReopenAudio() */
		return(-1);
	}

	/* Memory map the audio buffer */
	if ( ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0 ) {
		SDL_SetError("Couldn't get OSPACE parameters");
		return(-1);
	}
	spec->size = info.fragsize;
	spec->samples = spec->size / ((spec->format & 0xFF) / 8);
	spec->samples /= spec->channels;
	num_buffers = info.fragstotal;
	dma_len = num_buffers*spec->size;
	dma_buf = (Uint8 *)mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
							audio_fd, 0);
	if ( dma_buf == MAP_FAILED ) {
		SDL_SetError("DMA memory map failed");
		dma_buf = NULL;
		return(-1);
	}
	SDL_memset(dma_buf, spec->silence, dma_len);

	/* Check to see if we need to use select() workaround */
	{ char *workaround;
		workaround = SDL_getenv("SDL_DSP_NOSELECT");
		if ( workaround ) {
			frame_ticks = (float)(spec->samples*1000)/spec->freq;
			next_frame = SDL_GetTicks()+frame_ticks;
		}
	}

	/* Trigger audio playback */
	value = 0;
	ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
	value = PCM_ENABLE_OUTPUT;
	if ( ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0 ) {
		SDL_SetError("Couldn't trigger audio output");
		return(-1);
	}

	/* Get the parent process id (we're the parent of the audio thread) */
	parent = getpid();

	/* We're ready to rock and roll. :-) */
	return(0);
}
Пример #30
0
static int
ESD_OpenDevice(_THIS, const char *devname, int iscapture)
{
    esd_format_t format = (ESD_STREAM | ESD_PLAY);
    SDL_AudioFormat test_format = 0;
    int found = 0;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    this->hidden->audio_fd = -1;

    /* Convert audio spec to the ESD audio format */
    /* Try for a closest match on audio format */
    for (test_format = SDL_FirstAudioFormat(this->spec.format);
         !found && test_format; test_format = SDL_NextAudioFormat()) {
#ifdef DEBUG_AUDIO
        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
#endif
        found = 1;
        switch (test_format) {
        case AUDIO_U8:
            format |= ESD_BITS8;
            break;
        case AUDIO_S16SYS:
            format |= ESD_BITS16;
            break;
        default:
            found = 0;
            break;
        }
    }

    if (!found) {
        ESD_CloseDevice(this);
        return SDL_SetError("Couldn't find any hardware audio formats");
    }

    if (this->spec.channels == 1) {
        format |= ESD_MONO;
    } else {
        format |= ESD_STEREO;
    }
#if 0
    this->spec.samples = ESD_BUF_SIZE;  /* Darn, no way to change this yet */
#endif

    /* Open a connection to the ESD audio server */
    this->hidden->audio_fd =
        SDL_NAME(esd_play_stream) (format, this->spec.freq, NULL,
                                   get_progname());

    if (this->hidden->audio_fd < 0) {
        ESD_CloseDevice(this);
        return SDL_SetError("Couldn't open ESD connection");
    }

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);
    this->hidden->frame_ticks =
        (float) (this->spec.samples * 1000) / this->spec.freq;
    this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        ESD_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

    /* Get the parent process id (we're the parent of the audio thread) */
    this->hidden->parent = getpid();

    /* We're ready to rock and roll. :-) */
    return 0;
}