summaryrefslogtreecommitdiff
path: root/src/sound
diff options
context:
space:
mode:
Diffstat (limited to 'src/sound')
-rw-r--r--src/sound/cocoa_s.c149
-rw-r--r--src/sound/cocoa_s.h10
-rw-r--r--src/sound/null_s.c13
-rw-r--r--src/sound/null_s.h10
-rw-r--r--src/sound/sdl_s.c47
-rw-r--r--src/sound/sdl_s.h10
-rw-r--r--src/sound/win32_s.c87
-rw-r--r--src/sound/win32_s.h10
8 files changed, 336 insertions, 0 deletions
diff --git a/src/sound/cocoa_s.c b/src/sound/cocoa_s.c
new file mode 100644
index 000000000..3b758ad71
--- /dev/null
+++ b/src/sound/cocoa_s.c
@@ -0,0 +1,149 @@
+/* $Id$ */
+
+/*****************************************************************************
+ * Cocoa sound driver *
+ * Known things left to do: *
+ * - Might need to do endian checking for it to work on both ppc and x86 *
+ *****************************************************************************/
+
+#ifdef WITH_COCOA
+
+#include <AudioUnit/AudioUnit.h>
+
+/* Name conflict */
+#define Rect OTTDRect
+#define Point OTTDPoint
+#define WindowClass OTTDWindowClass
+/* Defined in stdbool.h */
+#ifndef __cplusplus
+# ifndef __BEOS__
+# undef bool
+# undef false
+# undef true
+# endif
+#endif
+
+#include "../stdafx.h"
+#include "../openttd.h"
+#include "../debug.h"
+#include "../driver.h"
+#include "../mixer.h"
+#include "../sdl.h"
+
+#include "cocoa_s.h"
+
+#undef WindowClass
+#undef Point
+#undef Rect
+
+
+static AudioUnit _outputAudioUnit;
+
+/* The CoreAudio callback */
+static OSStatus audioCallback(void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, AudioBuffer *ioData)
+{
+ MxMixSamples(ioData->mData, ioData->mDataByteSize / 4);
+
+ return noErr;
+}
+
+
+static const char *CocoaSoundStart(const char * const *parm)
+{
+ Component comp;
+ ComponentDescription desc;
+ struct AudioUnitInputCallback callback;
+ AudioStreamBasicDescription requestedDesc;
+
+ /* Setup a AudioStreamBasicDescription with the requested format */
+ requestedDesc.mFormatID = kAudioFormatLinearPCM;
+ requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
+ requestedDesc.mChannelsPerFrame = 2;
+ requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 11025);
+
+ requestedDesc.mBitsPerChannel = 16;
+ requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+
+#ifdef TTD_BIG_ENDIAN
+ requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
+#endif
+
+ requestedDesc.mFramesPerPacket = 1;
+ requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8;
+ requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket;
+
+
+ /* Locate the default output audio unit */
+ desc.componentType = kAudioUnitComponentType;
+ desc.componentSubType = kAudioUnitSubType_Output;
+ desc.componentManufacturer = kAudioUnitID_DefaultOutput;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+
+ comp = FindNextComponent (NULL, &desc);
+ if (comp == NULL) {
+ return "cocoa_s: Failed to start CoreAudio: FindNextComponent returned NULL";
+ }
+
+ /* Open & initialize the default output audio unit */
+ if (OpenAComponent(comp, &_outputAudioUnit) != noErr) {
+ return "cocoa_s: Failed to start CoreAudio: OpenAComponent";
+ }
+
+ if (AudioUnitInitialize(_outputAudioUnit) != noErr) {
+ return "cocoa_s: Failed to start CoreAudio: AudioUnitInitialize";
+ }
+
+ /* Set the input format of the audio unit. */
+ if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)) != noErr) {
+ return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)";
+ }
+
+ /* Set the audio callback */
+ callback.inputProc = audioCallback;
+ callback.inputProcRefCon = NULL;
+ if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
+ return "cocoa_s: Failed to start CoreAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)";
+ }
+
+ /* Finally, start processing of the audio unit */
+ if (AudioOutputUnitStart(_outputAudioUnit) != noErr) {
+ return "cocoa_s: Failed to start CoreAudio: AudioOutputUnitStart";
+ }
+
+ /* We're running! */
+ return NULL;
+}
+
+
+static void CocoaSoundStop(void)
+{
+ struct AudioUnitInputCallback callback;
+
+ /* stop processing the audio unit */
+ if (AudioOutputUnitStop(_outputAudioUnit) != noErr) {
+ DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioOutputUnitStop failed");
+ return;
+ }
+
+ /* Remove the input callback */
+ callback.inputProc = 0;
+ callback.inputProcRefCon = 0;
+ if (AudioUnitSetProperty(_outputAudioUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)) != noErr) {
+ DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback) failed");
+ return;
+ }
+
+ if (CloseComponent(_outputAudioUnit) != noErr) {
+ DEBUG(driver, 0, "cocoa_s: Core_CloseAudio: CloseComponent failed");
+ return;
+ }
+}
+
+
+const HalSoundDriver _cocoa_sound_driver = {
+ CocoaSoundStart,
+ CocoaSoundStop,
+};
+
+#endif /* WITH_COCOA */
diff --git a/src/sound/cocoa_s.h b/src/sound/cocoa_s.h
new file mode 100644
index 000000000..7db5f7023
--- /dev/null
+++ b/src/sound/cocoa_s.h
@@ -0,0 +1,10 @@
+/* $Id$ */
+
+#ifndef SOUND_COCOA_H
+#define SOUND_COCOA_H
+
+#include "../hal.h"
+
+extern const HalSoundDriver _cocoa_sound_driver;
+
+#endif
diff --git a/src/sound/null_s.c b/src/sound/null_s.c
new file mode 100644
index 000000000..f68c4b13a
--- /dev/null
+++ b/src/sound/null_s.c
@@ -0,0 +1,13 @@
+/* $Id$ */
+
+#include "../stdafx.h"
+#include "../openttd.h"
+#include "null_s.h"
+
+static const char *NullSoundStart(const char * const *parm) { return NULL; }
+static void NullSoundStop(void) {}
+
+const HalSoundDriver _null_sound_driver = {
+ NullSoundStart,
+ NullSoundStop,
+};
diff --git a/src/sound/null_s.h b/src/sound/null_s.h
new file mode 100644
index 000000000..6ccd19aed
--- /dev/null
+++ b/src/sound/null_s.h
@@ -0,0 +1,10 @@
+/* $Id$ */
+
+#ifndef SOUND_NULL_H
+#define SOUND_NULL_H
+
+#include "../hal.h"
+
+extern const HalSoundDriver _null_sound_driver;
+
+#endif
diff --git a/src/sound/sdl_s.c b/src/sound/sdl_s.c
new file mode 100644
index 000000000..4b1da52d6
--- /dev/null
+++ b/src/sound/sdl_s.c
@@ -0,0 +1,47 @@
+/* $Id$ */
+
+#include "../stdafx.h"
+
+#ifdef WITH_SDL
+
+#include "../openttd.h"
+#include "../driver.h"
+#include "../mixer.h"
+#include "../sdl.h"
+#include "sdl_s.h"
+#include <SDL.h>
+
+static void CDECL fill_sound_buffer(void *userdata, Uint8 *stream, int len)
+{
+ MxMixSamples(stream, len / 4);
+}
+
+static const char *SdlSoundStart(const char * const *parm)
+{
+ SDL_AudioSpec spec;
+
+ const char *s = SdlOpen(SDL_INIT_AUDIO);
+ if (s != NULL) return s;
+
+ spec.freq = GetDriverParamInt(parm, "hz", 11025);
+ spec.format = AUDIO_S16SYS;
+ spec.channels = 2;
+ spec.samples = 512;
+ spec.callback = fill_sound_buffer;
+ SDL_CALL SDL_OpenAudio(&spec, &spec);
+ SDL_CALL SDL_PauseAudio(0);
+ return NULL;
+}
+
+static void SdlSoundStop(void)
+{
+ SDL_CALL SDL_CloseAudio();
+ SdlClose(SDL_INIT_AUDIO);
+}
+
+const HalSoundDriver _sdl_sound_driver = {
+ SdlSoundStart,
+ SdlSoundStop,
+};
+
+#endif
diff --git a/src/sound/sdl_s.h b/src/sound/sdl_s.h
new file mode 100644
index 000000000..6fc2b6dc0
--- /dev/null
+++ b/src/sound/sdl_s.h
@@ -0,0 +1,10 @@
+/* $Id$ */
+
+#ifndef SOUND_SDL_H
+#define SOUND_SDL_H
+
+#include "../hal.h"
+
+extern const HalSoundDriver _sdl_sound_driver;
+
+#endif
diff --git a/src/sound/win32_s.c b/src/sound/win32_s.c
new file mode 100644
index 000000000..a39cee985
--- /dev/null
+++ b/src/sound/win32_s.c
@@ -0,0 +1,87 @@
+/* $Id$ */
+
+#include "../stdafx.h"
+#include "../openttd.h"
+#include "../driver.h"
+#include "../functions.h"
+#include "../mixer.h"
+#include "win32_s.h"
+#include <windows.h>
+#include <mmsystem.h>
+
+static HWAVEOUT _waveout;
+static WAVEHDR _wave_hdr[2];
+static int _bufsize;
+
+static void PrepareHeader(WAVEHDR *hdr)
+{
+ hdr->dwBufferLength = _bufsize * 4;
+ hdr->dwFlags = 0;
+ hdr->lpData = malloc(_bufsize * 4);
+ if (hdr->lpData == NULL ||
+ waveOutPrepareHeader(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
+ error("waveOutPrepareHeader failed");
+}
+
+static void FillHeaders(void)
+{
+ WAVEHDR *hdr;
+
+ for (hdr = _wave_hdr; hdr != endof(_wave_hdr); hdr++) {
+ if (!(hdr->dwFlags & WHDR_INQUEUE)) {
+ MxMixSamples(hdr->lpData, hdr->dwBufferLength / 4);
+ if (waveOutWrite(_waveout, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
+ error("waveOutWrite failed");
+ }
+ }
+}
+
+static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
+ DWORD dwParam1, DWORD dwParam2)
+{
+ switch (uMsg) {
+ case WOM_DONE:
+ if (_waveout) FillHeaders();
+ break;
+
+ default:
+ break;
+ }
+}
+
+static const char *Win32SoundStart(const char* const* parm)
+{
+ WAVEFORMATEX wfex;
+ int hz;
+
+ _bufsize = GetDriverParamInt(parm, "bufsize", 1024);
+ hz = GetDriverParamInt(parm, "hz", 11025);
+ wfex.wFormatTag = WAVE_FORMAT_PCM;
+ wfex.nChannels = 2;
+ wfex.nSamplesPerSec = hz;
+ wfex.nAvgBytesPerSec = hz * 2 * 2;
+ wfex.nBlockAlign = 4;
+ wfex.wBitsPerSample = 16;
+ if (waveOutOpen(&_waveout, WAVE_MAPPER, &wfex, (DWORD_PTR)&waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
+ return "waveOutOpen failed";
+ PrepareHeader(&_wave_hdr[0]);
+ PrepareHeader(&_wave_hdr[1]);
+ FillHeaders();
+ return NULL;
+}
+
+static void Win32SoundStop(void)
+{
+ HWAVEOUT waveout = _waveout;
+
+ _waveout = NULL;
+ waveOutReset(waveout);
+ waveOutUnprepareHeader(waveout, &_wave_hdr[0], sizeof(WAVEHDR));
+ waveOutUnprepareHeader(waveout, &_wave_hdr[1], sizeof(WAVEHDR));
+ waveOutClose(waveout);
+}
+
+const HalSoundDriver _win32_sound_driver = {
+ Win32SoundStart,
+ Win32SoundStop,
+};
diff --git a/src/sound/win32_s.h b/src/sound/win32_s.h
new file mode 100644
index 000000000..65c6a957d
--- /dev/null
+++ b/src/sound/win32_s.h
@@ -0,0 +1,10 @@
+/* $Id$ */
+
+#ifndef SOUND_WIN32_H
+#define SOUND_WIN32_H
+
+#include "../hal.h"
+
+extern const HalSoundDriver _win32_sound_driver;
+
+#endif