summaryrefslogtreecommitdiff
path: root/src/libs/sound/mixer/nosound/audiodrv_nosound.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/sound/mixer/nosound/audiodrv_nosound.c')
-rw-r--r--src/libs/sound/mixer/nosound/audiodrv_nosound.c410
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);
+}