diff options
Diffstat (limited to 'src/libs/sound/mixer/nosound/audiodrv_nosound.c')
-rw-r--r-- | src/libs/sound/mixer/nosound/audiodrv_nosound.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/src/libs/sound/mixer/nosound/audiodrv_nosound.c b/src/libs/sound/mixer/nosound/audiodrv_nosound.c new file mode 100644 index 0000000..005bb44 --- /dev/null +++ b/src/libs/sound/mixer/nosound/audiodrv_nosound.c @@ -0,0 +1,410 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Nosound audio driver + */ + +#include "audiodrv_nosound.h" +#include "../../sndintrn.h" +#include "libs/tasklib.h" +#include "libs/log.h" +#include "libs/memlib.h" +#include <stdlib.h> + + +static Task PlaybackTask; +static uint32 nosound_freq = 22050; + +static const audio_Driver noSound_Driver = +{ + noSound_Uninit, + noSound_GetError, + audio_DRIVER_NOSOUND, + { + /* Errors */ + MIX_NO_ERROR, + MIX_INVALID_NAME, + MIX_INVALID_ENUM, + MIX_INVALID_VALUE, + MIX_INVALID_OPERATION, + MIX_OUT_OF_MEMORY, + MIX_DRIVER_FAILURE, + + /* Source properties */ + MIX_POSITION, + MIX_LOOPING, + MIX_BUFFER, + MIX_GAIN, + MIX_SOURCE_STATE, + MIX_BUFFERS_QUEUED, + MIX_BUFFERS_PROCESSED, + + /* Source state information */ + MIX_INITIAL, + MIX_STOPPED, + MIX_PLAYING, + MIX_PAUSED, + + /* Sound buffer properties */ + MIX_FREQUENCY, + MIX_BITS, + MIX_CHANNELS, + MIX_SIZE, + MIX_FORMAT_MONO16, + MIX_FORMAT_STEREO16, + MIX_FORMAT_MONO8, + MIX_FORMAT_STEREO8 + }, + + /* Sources */ + noSound_GenSources, + noSound_DeleteSources, + noSound_IsSource, + noSound_Sourcei, + noSound_Sourcef, + noSound_Sourcefv, + noSound_GetSourcei, + noSound_GetSourcef, + noSound_SourceRewind, + noSound_SourcePlay, + noSound_SourcePause, + noSound_SourceStop, + noSound_SourceQueueBuffers, + noSound_SourceUnqueueBuffers, + + /* Buffers */ + noSound_GenBuffers, + noSound_DeleteBuffers, + noSound_IsBuffer, + noSound_GetBufferi, + noSound_BufferData +}; + + +/* + * Initialization + */ + +sint32 +noSound_Init (audio_Driver *driver, sint32 flags) +{ + int i; + TFB_DecoderFormats formats = + { + 0, 0, + audio_FORMAT_MONO8, audio_FORMAT_STEREO8, + audio_FORMAT_MONO16, audio_FORMAT_STEREO16 + }; + + log_add (log_Info, "Using nosound audio driver."); + log_add (log_Info, "Initializing mixer."); + + if (!mixer_Init (nosound_freq, MIX_FORMAT_MAKE (1, 1), + MIX_QUALITY_LOW, MIX_FAKE_DATA)) + { + log_add (log_Error, "Mixer initialization failed: %x", + mixer_GetError ()); + return -1; + } + log_add (log_Info, "Mixer initialized."); + + log_add (log_Info, "Initializing sound decoders."); + if (SoundDecoder_Init (flags, &formats)) + { + log_add (log_Error, "Sound decoders initialization failed."); + mixer_Uninit (); + return -1; + } + log_add (log_Info, "Sound decoders initialized."); + + *driver = noSound_Driver; + for (i = 0; i < NUM_SOUNDSOURCES; ++i) + { + audio_GenSources (1, &soundSource[i].handle); + soundSource[i].stream_mutex = CreateMutex ("Nosound stream mutex", SYNC_CLASS_AUDIO); + } + + if (InitStreamDecoder ()) + { + log_add (log_Error, "Stream decoder initialization failed."); + // TODO: cleanup source mutexes [or is it "muti"? :) ] + SoundDecoder_Uninit (); + mixer_Uninit (); + return -1; + } + + PlaybackTask = AssignTask (PlaybackTaskFunc, 1024, + "nosound audio playback"); + + return 0; +} + +void +noSound_Uninit (void) +{ + int i; + + UninitStreamDecoder (); + + for (i = 0; i < NUM_SOUNDSOURCES; ++i) + { + if (soundSource[i].sample && soundSource[i].sample->decoder) + { + StopStream (i); + } + if (soundSource[i].sbuffer) + { + void *sbuffer = soundSource[i].sbuffer; + soundSource[i].sbuffer = NULL; + HFree (sbuffer); + } + DestroyMutex (soundSource[i].stream_mutex); + + noSound_DeleteSources (1, &soundSource[i].handle); + } + + if (PlaybackTask) + { + ConcludeTask (PlaybackTask); + PlaybackTask = 0; + } + + mixer_Uninit (); + SoundDecoder_Uninit (); +} + + +/* + * Playback task + */ + +int +PlaybackTaskFunc (void *data) +{ + Task task = (Task)data; + uint8 *stream; + uint32 entryTime; + sint32 period, delay; + uint32 len = 2048; + + stream = (uint8 *) HMalloc (len); + period = (sint32)((len / (double)nosound_freq) * ONE_SECOND); + + while (!Task_ReadState (task, TASK_EXIT)) + { + entryTime = GetTimeCounter (); + mixer_MixFake (NULL, stream, len); + delay = period - (GetTimeCounter () - entryTime); + if (delay > 0) + HibernateThread (delay); + } + + HFree (stream); + FinishTask (task); + return 0; +} + + +/* + * General + */ + +sint32 +noSound_GetError (void) +{ + sint32 value = mixer_GetError (); + switch (value) + { + case MIX_NO_ERROR: + return audio_NO_ERROR; + case MIX_INVALID_NAME: + return audio_INVALID_NAME; + case MIX_INVALID_ENUM: + return audio_INVALID_ENUM; + case MIX_INVALID_VALUE: + return audio_INVALID_VALUE; + case MIX_INVALID_OPERATION: + return audio_INVALID_OPERATION; + case MIX_OUT_OF_MEMORY: + return audio_OUT_OF_MEMORY; + default: + log_add (log_Debug, "noSound_GetError: unknown value %x", + value); + return audio_DRIVER_FAILURE; + break; + } +} + + +/* + * Sources + */ + +void +noSound_GenSources (uint32 n, audio_Object *psrcobj) +{ + mixer_GenSources (n, (mixer_Object *) psrcobj); +} + +void +noSound_DeleteSources (uint32 n, audio_Object *psrcobj) +{ + mixer_DeleteSources (n, (mixer_Object *) psrcobj); +} + +bool +noSound_IsSource (audio_Object srcobj) +{ + return mixer_IsSource ((mixer_Object) srcobj); +} + +void +noSound_Sourcei (audio_Object srcobj, audio_SourceProp pname, + audio_IntVal value) + +{ + mixer_Sourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, + (mixer_IntVal) value); +} + +void +noSound_Sourcef (audio_Object srcobj, audio_SourceProp pname, + float value) +{ + mixer_Sourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); +} + +void +noSound_Sourcefv (audio_Object srcobj, audio_SourceProp pname, + float *value) +{ + mixer_Sourcefv ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); +} + +void +noSound_GetSourcei (audio_Object srcobj, audio_SourceProp pname, + audio_IntVal *value) +{ + mixer_GetSourcei ((mixer_Object) srcobj, (mixer_SourceProp) pname, + (mixer_IntVal *) value); + if (pname == MIX_SOURCE_STATE) + { + switch (*value) + { + case MIX_INITIAL: + *value = audio_INITIAL; + break; + case MIX_STOPPED: + *value = audio_STOPPED; + break; + case MIX_PLAYING: + *value = audio_PLAYING; + break; + case MIX_PAUSED: + *value = audio_PAUSED; + break; + default: + log_add (log_Debug, "noSound_GetSourcei(): unknown value %lx", + (long int) *value); + *value = audio_DRIVER_FAILURE; + } + } +} + +void +noSound_GetSourcef (audio_Object srcobj, audio_SourceProp pname, + float *value) +{ + mixer_GetSourcef ((mixer_Object) srcobj, (mixer_SourceProp) pname, value); +} + +void +noSound_SourceRewind (audio_Object srcobj) +{ + mixer_SourceRewind ((mixer_Object) srcobj); +} + +void +noSound_SourcePlay (audio_Object srcobj) +{ + mixer_SourcePlay ((mixer_Object) srcobj); +} + +void +noSound_SourcePause (audio_Object srcobj) +{ + mixer_SourcePause ((mixer_Object) srcobj); +} + +void +noSound_SourceStop (audio_Object srcobj) +{ + mixer_SourceStop ((mixer_Object) srcobj); +} + +void +noSound_SourceQueueBuffers (audio_Object srcobj, uint32 n, + audio_Object* pbufobj) +{ + mixer_SourceQueueBuffers ((mixer_Object) srcobj, n, + (mixer_Object *) pbufobj); +} + +void +noSound_SourceUnqueueBuffers (audio_Object srcobj, uint32 n, + audio_Object* pbufobj) +{ + mixer_SourceUnqueueBuffers ((mixer_Object) srcobj, n, + (mixer_Object *) pbufobj); +} + + +/* + * Buffers + */ + +void +noSound_GenBuffers (uint32 n, audio_Object *pbufobj) +{ + mixer_GenBuffers (n, (mixer_Object *) pbufobj); +} + +void +noSound_DeleteBuffers (uint32 n, audio_Object *pbufobj) +{ + mixer_DeleteBuffers (n, (mixer_Object *) pbufobj); +} + +bool +noSound_IsBuffer (audio_Object bufobj) +{ + return mixer_IsBuffer ((mixer_Object) bufobj); +} + +void +noSound_GetBufferi (audio_Object bufobj, audio_BufferProp pname, + audio_IntVal *value) +{ + mixer_GetBufferi ((mixer_Object) bufobj, (mixer_BufferProp) pname, + (mixer_IntVal *) value); +} + +void +noSound_BufferData (audio_Object bufobj, uint32 format, void* data, + uint32 size, uint32 freq) +{ + mixer_BufferData ((mixer_Object) bufobj, format, data, size, freq); +} |