summaryrefslogtreecommitdiff
path: root/tutorials/sndkit/samples/audiolevel.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /tutorials/sndkit/samples/audiolevel.c
downloadoss4-upstream/4.2-build2006.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'tutorials/sndkit/samples/audiolevel.c')
-rw-r--r--tutorials/sndkit/samples/audiolevel.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/tutorials/sndkit/samples/audiolevel.c b/tutorials/sndkit/samples/audiolevel.c
new file mode 100644
index 0000000..38734e3
--- /dev/null
+++ b/tutorials/sndkit/samples/audiolevel.c
@@ -0,0 +1,202 @@
+/*
+ * Purpose: A simple program that does audio recording.
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This is a very minimal program that does audio recording. However to
+ * demonstrate processiong of audio data it computes the
+ * maximum value of the signal and displays a "LED" bars
+ * (using character mode console).
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <soundcard.h>
+
+int fd_in;
+int sample_rate = 48000;
+
+/*
+ * The open_audio_device opens the audio device and initializes it
+ * for the required mode. The same routine is used in the other
+ * simple sample programs too.
+ */
+
+static int
+open_audio_device (char *name, int mode)
+{
+ int tmp, fd;
+
+ if ((fd = open (name, mode, 0)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+
+/*
+ * Setup the device. Note that it's important to set the
+ * sample format, number of channels and sample rate exactly in this order.
+ * Some devices depend on the order.
+ */
+
+/*
+ * Set the sample format
+ */
+ tmp = AFMT_S16_NE; /* Native 16 bits */
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_SETFMT");
+ exit (-1);
+ }
+
+ if (tmp != AFMT_S16_NE)
+ {
+ fprintf (stderr,
+ "The device doesn't support the 16 bit sample format.\n");
+ exit (-1);
+ }
+
+/*
+ * Set the number of channels (mono)
+ */
+ tmp = 1;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_CHANNELS");
+ exit (-1);
+ }
+
+ if (tmp != 1)
+ {
+ fprintf (stderr, "The device doesn't support mono mode.\n");
+ exit (-1);
+ }
+
+/*
+ * Set the sample rate
+ */
+ sample_rate = 48000;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &sample_rate) == -1)
+ {
+ perror ("SNDCTL_DSP_SPEED");
+ exit (-1);
+ }
+
+/*
+ * No need for error checking because we will automatically adjust the
+ * signal based on the actual sample rate. However most application must
+ * check the value of sample_rate and compare it to the requested rate.
+ *
+ * Small differences between the rates (10% or less) are normal and the
+ * applications should usually tolerate them. However larger differences may
+ * cause annoying pitch problems (Mickey Mouse).
+ */
+
+ return fd;
+}
+
+void
+process_input (void)
+{
+ short buffer[1024];
+
+ int l, i, level;
+
+/*
+ * First read a block of audio samples with proper error checking.
+ */
+
+ if ((l = read (fd_in, buffer, sizeof (buffer))) == -1)
+ {
+ perror ("Audio read");
+ exit (-1); /* Or return an error code */
+ }
+
+/*
+ * We are using 16 bit samples so the number of bytes returned by read must be
+ * converted to the number of samples (2 bytes per a 16 bit sample).
+ *
+ * Some care must be taken if this program is converted from 1 channels
+ * (mono) to 2 channels (stereo) or more.
+ *
+ * Handling more than 1 channels is bit more complicated because the channels
+ * are interleaved. This will be demonstrated in some other programs.
+ */
+
+ l = l / 2;
+
+/*
+ * After this point this routine will perform the peak volume computations.
+ * The {!code l} variable contains the number of samples in the buffer.
+ *
+ * The remaining lines can be removed and replaced with the required
+ * application code.
+ */
+
+ level = 0;
+
+ for (i = 0; i < l; i++)
+ {
+/*
+ * Take the next sample (i) and compute it's absolute value. Check if it
+ * was larger than the previous peak value.
+ */
+ int v = buffer[i];
+
+ if (v < 0)
+ v = -v; /* abs */
+
+ if (v > level)
+ level = v;
+ }
+
+/*
+ * Finally print the simple LED bar. The maximum value for a 16 bit
+ * sample is 32*1024-1. Convert this to 32 bars.
+ *
+ * This program uses linear scale for simplicity. Real world audio programs
+ * should probably use logarithmic scale (dB).
+ */
+
+ level = (level + 1) / 1024;
+
+ for (i = 0; i < level; i++)
+ printf ("*");
+ for (i = level; i < 32; i++)
+ printf (".");
+ printf ("\r");
+ fflush (stdout);
+}
+
+int
+main (int argc, char *argv[])
+{
+/*
+ * Use /dev/dsp as the default device because the system administrator
+ * may select the device using the {!xlink ossctl} program or some other
+ * methods
+ */
+ char *name_in = "/dev/dsp";
+
+/*
+ * It's recommended to provide some method for selecting some other
+ * device than the default. We use command line argument but in some cases
+ * an environment variable or some configuration file setting may be better.
+ */
+ if (argc > 1)
+ name_in = argv[1];
+
+/*
+ * It's mandatory to use O_RDONLY in programs that do only recording. Other
+ * modes may cause increased resource (memory) usage in the driver. It may
+ * also prevent other applications from using the same device for
+ * playback at the same time.
+ */
+ fd_in = open_audio_device (name_in, O_RDONLY);
+
+ while (1)
+ process_input ();
+
+ exit (0);
+}