aboutsummaryrefslogtreecommitdiff
path: root/src/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio.c')
-rw-r--r--src/audio.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/audio.c b/src/audio.c
new file mode 100644
index 0000000..ed37a89
--- /dev/null
+++ b/src/audio.c
@@ -0,0 +1,159 @@
+/*
+ * audio.c
+ *
+ * Moo like a cow
+ *
+ * (c) 2008 Thomas White <taw27@srcf.ucam.org>
+ *
+ * This file is part of OpenMooCow - accelerometer moobox simulator
+ *
+ * OpenMooCow 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenMooCow 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 OpenMooCow. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+//#ifdef HAVE_CONFIG_H
+//#include <config.h>
+//#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_audio.h>
+#include <math.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "types.h"
+
+static void audio_mix(void *data, Uint8 *stream8, int len) {
+
+ AudioContext *a = data;
+ int j;
+ Sint16 *stream = (Sint16 *)stream8;
+ Sint16 samp;
+
+ len /= 2; /* Number of samples to write */
+
+ for ( j=0; j<len; j++ ) {
+
+ stream[j] = 0;
+
+ if ( a->moo_pos < a->moo_len ) {
+ samp = a->moo_buf[a->moo_pos++];
+ stream[j] += samp;
+ }
+
+ }
+
+}
+
+void audio_trigger_moo(AudioContext *a) {
+
+ if ( a->aplay_fallback ) {
+
+ pid_t pid;
+ int status;
+
+ pid = fork();
+ if ( !( (pid != 0) && (pid != -1) ) ) {
+ if ( pid == -1 ) {
+ fprintf(stderr, "fork() failed.\n");
+ return;
+ } else {
+ /* Forked successfully, child process */
+ execlp("aplay", "aplay", DATADIR"/openmoocow/moo.wav", NULL);
+ }
+ } /* else forked successfully, parent process */
+ printf("Waiting...\n"); fflush(stdout);
+ waitpid(pid, &status, 0);
+ printf("Done mooing\n"); fflush(stdout);
+
+ } else {
+ if ( a->moo_pos == a->moo_len ) {
+ a->moo_pos = 0;
+ }
+ }
+
+}
+
+/* SDL audio initial setup */
+AudioContext *audio_setup() {
+
+ AudioContext *a;
+ SDL_AudioSpec fmt;
+ SDL_AudioSpec wave;
+ Uint8 *data;
+ Uint32 dlen;
+ SDL_AudioCVT cvt;
+
+ /* Create audio context */
+ a = malloc(sizeof(AudioContext));
+ if ( a == NULL ) return NULL;
+
+ /* 16-bit mono audio at 44.1 kHz */
+ fmt.freq = 44100;
+ fmt.format = AUDIO_S16;
+ fmt.channels = 1;
+ fmt.samples = 512;
+ fmt.callback = audio_mix;
+ fmt.userdata = a;
+ fmt.silence = 0;
+
+ if ( SDL_OpenAudio(&fmt, NULL) < 0 ) {
+ fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
+ a->aplay_fallback = 1;
+ return a;
+ }
+ a->aplay_fallback = 0;
+
+ if ( SDL_LoadWAV(DATADIR"/openmoocow/moo.wav", &wave, &data, &dlen) == NULL ) {
+ fprintf(stderr, "Couldn't load moo sound: %s\n", SDL_GetError());
+ return a;
+ }
+ SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq, AUDIO_S16, 1, 44100);
+ cvt.buf = malloc(dlen*cvt.len_mult);
+ if ( cvt.buf == NULL ) {
+ fprintf(stderr, "Not enough memory to convert audio \n");
+ return a;
+ }
+ memcpy(cvt.buf, data, dlen);
+ cvt.len = dlen;
+ SDL_ConvertAudio(&cvt);
+ SDL_FreeWAV(data);
+
+ a->moo_len = cvt.len_cvt/2 - 2; /* Convert bytes to samples */
+ a->moo_pos = a->moo_len; /* Play nothing to start with */
+ a->moo_buf = (Sint16 *)cvt.buf;
+
+ SDL_PauseAudio(0);
+
+ return a;
+
+}
+
+void audio_shutdown(AudioContext *a) {
+
+ if ( a == NULL ) return;
+
+ if ( !a->aplay_fallback ) {
+ SDL_CloseAudio();
+ }
+
+ /* Now this can be freed */
+ free(a);
+
+}
+