📄 sdl_dx5audio.c
字号:
return(NULL); } cursor /= mixlen; playing = cursor; cursor = (cursor+1)%NUM_BUFFERS; cursor *= mixlen; /* Lock the audio buffer */ result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); if ( result == DSERR_BUFFERLOST ) { IDirectSoundBuffer_Restore(mixbuf); result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); } if ( result != DS_OK ) { SetDSerror("DirectSound Lock", result); return(NULL); } return(locked_buf);}static void DX5_WaitDone(_THIS){ Uint8 *stream; /* Wait for the playing chunk to finish */ stream = this->GetAudioBuf(this); if ( stream != NULL ) { memset(stream, silence, mixlen); this->PlayAudio(this); } this->WaitAudio(this); /* Stop the looping sound buffer */ IDirectSoundBuffer_Stop(mixbuf);}static void DX5_CloseAudio(_THIS){ if ( sound != NULL ) { if ( mixbuf != NULL ) { /* Clean up the audio buffer */ IDirectSoundBuffer_Release(mixbuf); mixbuf = NULL; } if ( audio_event != NULL ) { CloseHandle(audio_event); audio_event = NULL; } IDirectSound_Release(sound); sound = NULL; }}#ifdef USE_PRIMARY_BUFFER/* This function tries to create a primary audio buffer, and returns the number of audio chunks available in the created buffer.*/static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize){ HRESULT result; DSBUFFERDESC format; DSBCAPS caps; int numchunks; /* Try to set primary mixing privileges */ result = IDirectSound_SetCooperativeLevel(sndObj, focus, DSSCL_WRITEPRIMARY); if ( result != DS_OK ) {#ifdef DEBUG_SOUND SetDSerror("DirectSound SetCooperativeLevel", result);#endif return(-1); } /* Try to create the primary buffer */ memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); format.dwFlags |= DSBCAPS_STICKYFOCUS;#ifdef USE_POSITION_NOTIFY format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;#endif result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); if ( result != DS_OK ) {#ifdef DEBUG_SOUND SetDSerror("DirectSound CreateSoundBuffer", result);#endif return(-1); } /* Check the size of the fragment buffer */ memset(&caps, 0, sizeof(caps)); caps.dwSize = sizeof(caps); result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); if ( result != DS_OK ) {#ifdef DEBUG_SOUND SetDSerror("DirectSound GetCaps", result);#endif IDirectSoundBuffer_Release(*sndbuf); return(-1); } if ( (chunksize > caps.dwBufferBytes) || ((caps.dwBufferBytes%chunksize) != 0) ) { /* The primary buffer size is not a multiple of 'chunksize' -- this hopefully doesn't happen when 'chunksize' is a power of 2. */ IDirectSoundBuffer_Release(*sndbuf); SDL_SetError("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", caps.dwBufferBytes, chunksize); return(-1); } numchunks = (caps.dwBufferBytes/chunksize); /* Set the primary audio format */ result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); if ( result != DS_OK ) {#ifdef DEBUG_SOUND SetDSerror("DirectSound SetFormat", result);#endif IDirectSoundBuffer_Release(*sndbuf); return(-1); } return(numchunks);}#endif /* USE_PRIMARY_BUFFER *//* This function tries to create a secondary audio buffer, and returns the number of audio chunks available in the created buffer.*/static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize){ const int numchunks = 2; HRESULT result; DSBUFFERDESC format; LPVOID pvAudioPtr1, pvAudioPtr2; DWORD dwAudioBytes1, dwAudioBytes2; /* Try to set primary mixing privileges */ if ( focus ) { result = IDirectSound_SetCooperativeLevel(sndObj, focus, DSSCL_PRIORITY); } else { result = IDirectSound_SetCooperativeLevel(sndObj, GetDesktopWindow(), DSSCL_NORMAL); } if ( result != DS_OK ) {#ifdef DEBUG_SOUND SetDSerror("DirectSound SetCooperativeLevel", result);#endif return(-1); } /* Try to create the secondary buffer */ memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;#ifdef USE_POSITION_NOTIFY format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;#endif if ( ! focus ) { format.dwFlags |= DSBCAPS_GLOBALFOCUS; } else { format.dwFlags |= DSBCAPS_STICKYFOCUS; } format.dwBufferBytes = numchunks*chunksize; if ( (format.dwBufferBytes < DSBSIZE_MIN) || (format.dwBufferBytes > DSBSIZE_MAX) ) { SDL_SetError("Sound buffer size must be between %d and %d", DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); return(-1); } format.dwReserved = 0; format.lpwfxFormat = wavefmt; result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); if ( result != DS_OK ) { SetDSerror("DirectSound CreateSoundBuffer", result); return(-1); } IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); /* Silence the initial audio buffer */ result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes, (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, DSBLOCK_ENTIREBUFFER); if ( result == DS_OK ) { if ( wavefmt->wBitsPerSample == 8 ) { memset(pvAudioPtr1, 0x80, dwAudioBytes1); } else { memset(pvAudioPtr1, 0x00, dwAudioBytes1); } IDirectSoundBuffer_Unlock(*sndbuf, (LPVOID)pvAudioPtr1, dwAudioBytes1, (LPVOID)pvAudioPtr2, dwAudioBytes2); } /* We're ready to go */ return(numchunks);}/* This function tries to set position notify events on the mixing buffer */#ifdef USE_POSITION_NOTIFYstatic int CreateAudioEvent(_THIS){ LPDIRECTSOUNDNOTIFY notify; DSBPOSITIONNOTIFY *notify_positions; int i, retval; HRESULT result; /* Default to fail on exit */ retval = -1; notify = NULL; /* Query for the interface */ result = IDirectSoundBuffer_QueryInterface(mixbuf, &IID_IDirectSoundNotify, (void *)¬ify); if ( result != DS_OK ) { goto done; } /* Allocate the notify structures */ notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS* sizeof(*notify_positions)); if ( notify_positions == NULL ) { goto done; } /* Create the notify event */ audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); if ( audio_event == NULL ) { goto done; } /* Set up the notify structures */ for ( i=0; i<NUM_BUFFERS; ++i ) { notify_positions[i].dwOffset = i*mixlen; notify_positions[i].hEventNotify = audio_event; } result = IDirectSoundNotify_SetNotificationPositions(notify, NUM_BUFFERS, notify_positions); if ( result == DS_OK ) { retval = 0; }done: if ( notify != NULL ) { IDirectSoundNotify_Release(notify); } return(retval);}#endif /* USE_POSITION_NOTIFY */static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec){ HRESULT result; WAVEFORMATEX waveformat; /* Set basic WAVE format parameters */ memset(&waveformat, 0, sizeof(waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; /* Determine the audio parameters from the AudioSpec */ switch ( spec->format & 0xFF ) { case 8: /* Unsigned 8 bit audio data */ spec->format = AUDIO_U8; silence = 0x80; waveformat.wBitsPerSample = 8; break; case 16: /* Signed 16 bit audio data */ spec->format = AUDIO_S16; silence = 0x00; waveformat.wBitsPerSample = 16; break; default: SDL_SetError("Unsupported audio format"); return(-1); } waveformat.nChannels = spec->channels; waveformat.nSamplesPerSec = spec->freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample/8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(spec); /* Open the audio device */ result = DSoundCreate(NULL, &sound, NULL); if ( result != DS_OK ) { SetDSerror("DirectSoundCreate", result); return(-1); } /* Create the audio buffer to which we write */ NUM_BUFFERS = -1;#ifdef USE_PRIMARY_BUFFER if ( mainwin ) { NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, &waveformat, spec->size); }#endif /* USE_PRIMARY_BUFFER */ if ( NUM_BUFFERS < 0 ) { NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, &waveformat, spec->size); if ( NUM_BUFFERS < 0 ) { return(-1); }#ifdef DEBUG_SOUND fprintf(stderr, "Using secondary audio buffer\n");#endif }#ifdef DEBUG_SOUND else fprintf(stderr, "Using primary audio buffer\n");#endif /* The buffer will auto-start playing in DX5_WaitAudio() */ playing = 0; mixlen = spec->size;#ifdef USE_POSITION_NOTIFY /* See if we can use DirectX 6 event notification */ if ( CreateAudioEvent(this) == 0 ) { this->WaitAudio = DX6_WaitAudio_EventWait; } else { this->WaitAudio = DX5_WaitAudio_BusyWait; }#endif return(0);}static int DX5_AudioDelayMsec (_THIS){ DWORD cursor, write; HRESULT result; int odelay; /* char buffer[80]; */ result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &write);+ write = cursor / mixlen; write = (write+1)%NUM_BUFFERS; write *= mixlen; if (result == DS_OK) { /* * delay in msec is bytes * 1000 / (bytes per sample * channels * freq)+ */ odelay = (write - cursor); odelay *= 1000; odelay /= this->spec.channels; if (!(this->spec.format == AUDIO_U8 || this->spec.format == AUDIO_S8)) { odelay /= 2; // 2 bytes per sample } odelay /= this->spec.freq; return odelay; } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -