aboutsummaryrefslogtreecommitdiffstats
path: root/demos/modules/gaudio/play-wave/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'demos/modules/gaudio/play-wave/main.c')
-rw-r--r--demos/modules/gaudio/play-wave/main.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/demos/modules/gaudio/play-wave/main.c b/demos/modules/gaudio/play-wave/main.c
new file mode 100644
index 00000000..f15ec7a1
--- /dev/null
+++ b/demos/modules/gaudio/play-wave/main.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * This demo demonstrates the use of the GAUDOUT module to play a wave file.
+ *
+ */
+#include "gfx.h"
+
+/* Specify our timing parameters */
+#define MY_AUDIO_CHANNEL 0 /* Use channel 0 */
+#define MY_AUDIO_CHANNEL_IS_STEREO GAUDOUT_CHANNEL0_IS_STEREO /* Is it stereo? */
+
+// Storage for the wave header
+static char whdr[32];
+
+
+/*
+ * Application entry point.
+ */
+int main(void) {
+ font_t font;
+ GFILE *f;
+ char *errmsg;
+ uint32_t toplay;
+ uint32_t frequency;
+ ArrayDataFormat datafmt;
+ uint32_t len;
+ GAudioData *paud;
+
+ // Initialise everything
+ gfxInit();
+ errmsg = 0;
+
+ // Any font will do
+ font = gdispOpenFont("*");
+
+ // Allocate audio buffers - 4 x 512 byte buffers.
+ // You may need to increase this for slower cpu's.
+ // You may be able to decrease this for low latency operating systems.
+ if (!gaudioAllocBuffers(4, 512)) {
+ errmsg = "Err: No Memory";
+ goto theend;
+ }
+
+ // Open the wave file
+ if (!(f = gfileOpen("allwrong.wav", "r"))) {
+ errmsg = "Err: Open WAV";
+ goto theend;
+ }
+
+ // Read the wave header
+ if (gfileRead(f, whdr, 20) != 20) {
+ errmsg = "Err: Read hdr";
+ goto theend;
+ }
+
+ // Check the wave header
+ if (whdr[0] != 'R' || whdr[1] != 'I' || whdr[2] != 'F' || whdr[3] != 'F' // RIFF label
+ || whdr[8] != 'W' || whdr[9] != 'A' || whdr[10] != 'V' || whdr[11] != 'E' // WAVE label
+ || whdr[12] != 'f' || whdr[13] != 'm' || whdr[14] != 't' || whdr[15] != ' ' // fmt label
+ ) {
+ errmsg = "Err: Bad header";
+ goto theend;
+ }
+
+ // Read the fmt block
+ len = (((uint32_t)(uint8_t)whdr[16])<<0) | (((uint32_t)(uint8_t)whdr[17])<<8)
+ | (((uint32_t)(uint8_t)whdr[18])<<16) | (((uint32_t)(uint8_t)whdr[19])<<24);
+ if (len > sizeof(whdr) || len < 16) {
+ errmsg = "Err: Bad fmt len";
+ goto theend;
+ }
+ if (gfileRead(f, whdr, len) != len) {
+ errmsg = "Err: Read fmt block";
+ goto theend;
+ }
+ if (whdr[0] != 1 || whdr[1] != 0 // PCM format
+ || (whdr[14] != 8 && whdr[14] != 16) || whdr[15] != 0 // 8 or 16 bits per sample
+ ) {
+ errmsg = "Err: Bad fmt block";
+ goto theend;
+ }
+
+ // Check stereo/mono
+ #if MY_AUDIO_CHANNEL_IS_STEREO
+ if (whdr[2] != 2 || whdr[3] != 0) {
+ errmsg = "Err: Not stereo";
+ goto theend;
+ }
+ #else
+ if (whdr[2] != 1 || whdr[3] != 0) {
+ errmsg = "Err: Not mono";
+ goto theend;
+ }
+ #endif
+
+ // Get the sample frequency (little endian format) and format
+ frequency = (((uint32_t)(uint8_t)whdr[4])<<0) | (((uint32_t)(uint8_t)whdr[5])<<8)
+ | (((uint32_t)(uint8_t)whdr[6])<<16) | (((uint32_t)(uint8_t)whdr[7])<<24);
+ datafmt = whdr[14] == 8 ? ARRAY_DATA_8BITUNSIGNED : ARRAY_DATA_16BITSIGNED;
+
+ // Initialise the audio output device
+ if (!gaudioPlayInit(MY_AUDIO_CHANNEL, frequency, datafmt)) {
+ // For this demo we don't try and do any format conversions if the driver won't accept
+ // what we initially request.
+ errmsg = "Err: Bad format/freq";
+ goto theend;
+ }
+
+ // Get our current file position
+ len += 20;
+
+ // Read RIFF blocks until we get to the data RIFF block (contains the audio)
+ while(TRUE) {
+ if (gfileRead(f, whdr, 8) != 8) {
+ errmsg = "Err: Read block";
+ goto theend;
+ }
+
+ // Get the block length (little endian format)
+ toplay = (((uint32_t)(uint8_t)whdr[4])<<0) | (((uint32_t)(uint8_t)whdr[5])<<8)
+ | (((uint32_t)(uint8_t)whdr[6])<<16) | (((uint32_t)(uint8_t)whdr[7])<<24);
+
+ // Stop scanning when this is a data block
+ if (whdr[0] == 'd' && whdr[1] == 'a' && whdr[2] == 't' && whdr[3] == 'a')
+ break;
+
+ // Seek to the next block header
+ len += toplay + 8;
+ if (!gfileSetPos(f, len)) {
+ errmsg = "Err: No data";
+ goto theend;
+ }
+ }
+
+ // Play the file
+ gdispDrawString(0, gdispGetHeight()/2, "Playing...", font, Yellow);
+ while(toplay) {
+ // Get a buffer to put the data into
+ paud = gaudioGetBuffer(TIME_INFINITE); // This should never fail as we are waiting forever
+
+ // How much data can we put in
+ len = toplay > paud->size ? paud->size : toplay;
+ paud->len = len;
+ toplay -= len;
+
+ // Read the data
+ if (gfileRead(f, paud+1, len) != len) {
+ errmsg = "Err: Read fail";
+ goto theend;
+ }
+
+ gaudioPlay(paud);
+ }
+ gfileClose(f);
+
+ // Wait for the play to finish
+ gaudioPlayWait(TIME_INFINITE);
+ gdispDrawString(0, gdispGetHeight()/2+10, "Done", font, Green);
+
+ // The end
+theend:
+ if (errmsg)
+ gdispDrawString(0, gdispGetHeight()/2, errmsg, font, Red);
+
+ while(TRUE)
+ gfxSleepMilliseconds(1000);
+}