Example #1
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. */
}
Example #2
0
ga_DeviceImpl_XAudio2* gaX_device_open_xaudio2(gc_int32 in_numBuffers, gc_int32 in_numSamples, ga_Format* in_format)
{
  ga_DeviceImpl_XAudio2* ret = gcX_ops->allocFunc(sizeof(ga_DeviceImpl_XAudio2));
  HRESULT result;
  WAVEFORMATEX fmt;
  gc_int32 i;
  ret->devType = GA_DEVICE_TYPE_XAUDIO2;
  ret->numBuffers = in_numBuffers;
  ret->numSamples = in_numSamples;
  memcpy(&ret->format, in_format, sizeof(ga_Format));
  ret->sampleSize = ga_format_sampleSize(in_format);
  ret->nextBuffer = 0;
  ret->xa = 0;
  ret->master = 0;

  CoInitializeEx(NULL, COINIT_MULTITHREADED);
  result = XAudio2Create(&ret->xa, 0, XAUDIO2_DEFAULT_PROCESSOR);
  if(FAILED(result))
    goto cleanup;

  result = IXAudio2_CreateMasteringVoice(ret->xa, &ret->master, 2, 44100, 0, 0, 0);
  if(FAILED(result))
    goto cleanup;

  fmt.cbSize = sizeof(WAVEFORMATEX);
  ZeroMemory(&fmt, sizeof(WAVEFORMATEX));
  fmt.cbSize = sizeof(WAVEFORMATEX);
  fmt.wFormatTag = WAVE_FORMAT_PCM;
  fmt.nChannels = 2;
  fmt.wBitsPerSample = 16;
  fmt.nSamplesPerSec = 44100;
  fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
  fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;

  result = IXAudio2_CreateSourceVoice(ret->xa, &ret->source, &fmt, XAUDIO2_VOICE_NOPITCH, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0);
  if(FAILED(result))
    goto cleanup;

  result =IXAudio2_StartEngine(ret->xa);
  if(FAILED(result))
    goto cleanup;

  result = IXAudio2SourceVoice_Start(ret->source, 0, XAUDIO2_COMMIT_NOW);
  if(FAILED(result))
    goto cleanup;

  ret->buffers = gcX_ops->allocFunc(ret->numBuffers * sizeof(void*));
  for(i = 0; i < ret->numBuffers; ++i)
    ret->buffers[i] = gcX_ops->allocFunc(ret->numSamples * ret->sampleSize);

  return ret;

cleanup:
  if(ret->source)
  {
    IXAudio2SourceVoice_Stop(ret->source, 0, XAUDIO2_COMMIT_NOW);
    IXAudio2SourceVoice_FlushSourceBuffers(ret->source);
    IXAudio2SourceVoice_DestroyVoice(ret->source);
  }
  if(ret->xa)
    IXAudio2_StopEngine(ret->xa);
  if(ret->master)
    IXAudio2MasteringVoice_DestroyVoice(ret->master);
  if(ret->xa)
    IXAudio2_Release(ret->xa);
  CoUninitialize();
  gcX_ops->freeFunc(ret);
  return 0;
}
Example #3
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. */
}
Example #4
0
File: snd.c Project: punesemu/puNES
BYTE snd_start(void) {
	int psamples;

	if (!cfg->apu.channel[APU_MASTER]) {
		return (EXIT_OK);
	}

	// come prima cosa blocco eventuali riproduzioni
	snd_stop();

	memset(&snd, 0x00, sizeof(_snd));
	memset(&xaudio2, 0x00, sizeof(xaudio2));
	memset(&cbd, 0x00, sizeof(_callback_data));
	snd.cache = &cbd;

	audio_channels(cfg->channels_mode);

	switch (cfg->samplerate) {
		case S48000:
			snd.samplerate = 48000;
			break;
		case S44100:
			snd.samplerate = 44100;
			break;
		case S22050:
			snd.samplerate = 22050;
			break;
		case S11025:
			snd.samplerate = 11025;
			break;
	}

	if (XAudio2Create(&xaudio2.engine, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
		MessageBox(NULL,
			"ATTENTION: Unable to create XAudio2 object. Probably you\n"
			"have an incomplete installation of DirectX 10."   ,
			"Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return (EXIT_ERROR);
	}

	if (IXAudio2_CreateMasteringVoice(xaudio2.engine, &xaudio2.master, snd.channels,
			snd.samplerate, 0, 0, NULL) != S_OK) {
		MessageBox(NULL,
			"ATTENTION: Unable to create XAudio2 master voice.",
			"Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return (EXIT_ERROR);
	}

	{
		WAVEFORMATEX wfm;

		memset(&wfm, 0, sizeof(wfm));

		wfm.wFormatTag = WAVE_FORMAT_PCM;
		wfm.nChannels = snd.channels;
		wfm.wBitsPerSample = 16;
		wfm.nSamplesPerSec = snd.samplerate;
		wfm.nBlockAlign = (wfm.nChannels * wfm.wBitsPerSample) / 8;
		wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign;
		wfm.cbSize = sizeof(wfm);

		if (IXAudio2_CreateSourceVoice(xaudio2.engine,
				&xaudio2.source,
				&wfm,
				XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH,
				XAUDIO2_DEFAULT_FREQ_RATIO,
				&callbacks,
				NULL,
				NULL) != S_OK) {
			MessageBox(NULL,
				"ATTENTION: Unable to create XAudio2 source voice.\n",
				"Error!",
				MB_ICONEXCLAMATION | MB_OK);
			return (EXIT_ERROR);
		}
	}

	{
		double factor = (1.0f / 48000.0f) * (double) snd.samplerate;

		psamples = ((1024 * factor) + ((512 * factor) * cfg->audio_buffer_factor));
	}

	snd.samples = psamples * 2;
	snd.frequency = machine.cpu_hz / (double) snd.samplerate;

	xaudio2.opened = TRUE;

#if !defined (RELEASE)
	xaudio2.tick = gui_get_ms();
#endif

	{
		// dimensione in bytes del buffer
		snd.buffer.size = (psamples * snd.channels * sizeof(*cbd.write)) * 5;

		snd.buffer.limit.low = (snd.buffer.size / 100) * 25;
		snd.buffer.limit.high = (snd.buffer.size / 100) * 55;

#if !defined (RELEASE)
		printf("softw bsize : %-6d - %-6d\n", snd.buffer.size, snd.samples);
		printf("softw limit : %-6d - %-6d\n", snd.buffer.limit.low, snd.buffer.limit.high);
#endif

		// alloco il buffer in memoria
		if (!(cbd.start = (SWORD *) malloc(snd.buffer.size))) {
			MessageBox(NULL,
				"ATTENTION: Unable to allocate audio buffers.\n",
				"Error!",
				MB_ICONEXCLAMATION | MB_OK);
			return (EXIT_ERROR);
		}

		if (!(cbd.silence = (SWORD *) malloc(snd.buffer.size))) {
			MessageBox(NULL,
				"ATTENTION: Unable to allocate silence buffer.\n",
				"Error!",
				MB_ICONEXCLAMATION | MB_OK);
			return (EXIT_ERROR);
		}

		// inizializzo il frame di scrittura
		cbd.write = cbd.start;
		// inizializzo il frame di lettura
		cbd.read = (SBYTE *) cbd.start;
		// punto alla fine del buffer
		cbd.end = cbd.read + snd.buffer.size;
		// creo il lock
		if ((xaudio2.semaphore = CreateSemaphore(NULL, 1, 2, NULL)) == NULL) {
			MessageBox(NULL,
				"ATTENTION: Unable to create XAudio2 semaphore.\n",
				"Error!",
				MB_ICONEXCLAMATION | MB_OK);
			return (EXIT_ERROR);
		}
		// azzero completamente i buffers
		memset(cbd.start, 0x00, snd.buffer.size);
		// azzero completamente il buffer del silenzio
		memset(cbd.silence, 0x00, snd.buffer.size);

		// azzero completamente la struttura XAUDIO2_BUFFER
		memset(&xaudio2.buffer, 0x00, sizeof(xaudio2.buffer));

		xaudio2.buffer.AudioBytes = psamples * sizeof(*cbd.write) * snd.channels;
		//xaudio2.buffer.pAudioData = (const BYTE *) cbd.read;
		xaudio2.buffer.pAudioData = (const BYTE *) cbd.silence;
		xaudio2.buffer.PlayBegin = 0;
		xaudio2.buffer.PlayLength = psamples;
		xaudio2.buffer.LoopBegin = 0;
		xaudio2.buffer.LoopLength = 0;
		xaudio2.buffer.LoopCount = 0;
		xaudio2.buffer.pContext = snd.cache;

		cbd.xa2buffer = &xaudio2.buffer;
		cbd.xa2source = xaudio2.source;
		cbd.lock = xaudio2.semaphore;

		if (IXAudio2SourceVoice_SubmitSourceBuffer(xaudio2.source,
		        (const XAUDIO2_BUFFER *) cbd.xa2buffer, NULL) != S_OK) {
			MessageBox(NULL,
				"ATTENTION: Unable to set sound engine.\n",
				"Error!",
				MB_ICONEXCLAMATION | MB_OK);
			return (EXIT_ERROR);
		}
	}

	if (extcl_snd_start) {
		extcl_snd_start((WORD) snd.samplerate);
	}

	audio_channels_init_mode();

	audio_quality(cfg->audio_quality);

	if(IXAudio2_StartEngine(xaudio2.engine) != S_OK) {
		MessageBox(NULL,
			"ATTENTION: Unable to start sound engine.\n",
			"Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return (EXIT_ERROR);
	}

	if(IXAudio2SourceVoice_Start(xaudio2.source, 0, XAUDIO2_COMMIT_NOW) != S_OK) {
		MessageBox(NULL,
			"ATTENTION: Unable to start source voice.\n",
			"Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return (EXIT_ERROR);
	}

	return (EXIT_OK);
}