Subject: maplay mpeg audio player for Linux
From: [email-masked] (Louis P. Kruger)
Date: Sun, 13 Mar 1994 17:51:57 GMT
Newsgroups: comp.os.linux.announce

Hi everybody!  I've added support for the Linux sound driver to 
Tobias Bading's very fine program maplay.  The original program
can be found on sunsite.unc.edu in /pub/electronic-publications/IUMA
This version only supports mono output, there wouldn't be too much
point in implementing stereo, because the playback is already a little
choppy as it is on my 486/66.  Pentium owners, enjoy! 
Since the patches aren't too long, I'm including them in this message.

	Louis

----------------------------CUT HERE---------------------------------------
--- ./configuration.sh~	Mon Feb 21 12:29:48 1994
+++ ./configuration.sh	Sat Mar 12 20:44:39 1994
@@ -46,9 +46,15 @@
      INCLUDEDIRS='-I/usr/gnu/lib/g++-include -I/usr/gnu/lib/gcc-lib/decstation/2.5.8/include'
      LIBRARIES=
      AUDIO_INCLUDES= ;;
+  "Linux*")
+	COMPILER=g++
+	COMPILERFLAGS='-O2 -m486 -funroll-loops -Wall -DLINUX -DDAMN_INTEL_BYTE_ORDER'
+	INCLUDEDIRS='-I/usr/g++-include/ -I/usr/lib/gcc-lib/i486-linux/2.5.8/include/'
+	LIBRARIES= 
+	AUDIO_INCLUDES='#include <sys/soundcard.h>' ;;
   *) echo "This programm has not been tested on your type of machine yet!"
      echo "Please modify the file configuration.sh according to your needs!"
      exit
 esac
 
 export COMPILER COMPILERFLAGS INCLUDEDIRS LIBRARIES
--- ./maplay.c~	Mon Feb 21 12:28:18 1994
+++ ./maplay.c	Sat Mar 12 19:28:25 1994
@@ -213,17 +213,26 @@
       Exit (1);
     }
 #else
-// #ifdef your_machine
-//    if (mode == single_channel || which_channels != both)
-//      buffer = new your_Obuffer (your_parameters);	// mono
-//    else
-//      buffer = new your_Obuffer (your_parameters);	// stereo
-// #else
+#ifdef LINUX
+  if (LinuxObuffer::class_suitable(
+       (mode == single_channel || which_channels != both) ? 1 : 2 ))
+  { 
+    if(mode == single_channel || which_channels != both)
+      buffer = new LinuxObuffer (1, header);
+    else
+      buffer = new LinuxObuffer (2, header);
+  }
+  else
+  {
+    cerr << "Sorry, no suitable audio device detected, please use stdout mode.\n";
+    Exit(1);
+  }
+#else
   {
     cerr << "Sorry, no suitable audio device detected, please use stdout mode.\n";
     Exit (1);
   }
-// #endif  // !your_machine
+#endif  // !LINUX
 #endif	// !SPARC
 #endif	// !Indigo
 
--- ./obuffer.c~	Mon Feb 21 12:28:21 1994
+++ ./obuffer.c	Sat Mar 12 19:42:43 1994
@@ -75,7 +75,122 @@
     bufferp[i] = buffer + i;
 }
 
+#ifdef LINUX
 
+int LinuxObuffer::audio_fd = -1;
+
+int LinuxObuffer::open_audio_device (void)
+{
+  int fd;
+
+  if ((fd = open ("/dev/dsp", O_WRONLY | O_NDELAY, 0)) < 0)
+    if (errno == EBUSY)
+    {
+      cerr << "Sorry, the audio device is busy!\n";
+      exit (1);
+    }
+    else
+    {
+      perror ("can't open /dev/dsp for writing");
+      exit (1);
+    }
+  return fd;
+}
+
+LinuxObuffer::LinuxObuffer (uint32 number_of_channels, Header *header)
+{
+#ifdef DEBUG
+  if (!number_of_channels || number_of_channels > MAXCHANNELS)
+  {
+    cerr << "LinuxObuffer: 0 < number of channels < " << MAXCHANNELS << "!\n";
+    exit (1);
+  }
+#endif
+  channels = number_of_channels;
+  for (int i = 0; i < number_of_channels; ++i)
+    bufferp[i] = buffer + i;
+
+  if (audio_fd < 0)
+  {
+    cerr << "Internal error, LinuxObuffer::audio_fd has to be initialized\n"
+	    "by LinuxObuffer::class_suitable()!\n";
+    exit (1);
+  }
+
+  // configure the device:
+  int play_precision = 16;
+  int play_stereo = channels-1;
+  int play_sample_rate = header->frequency ();
+
+  if(
+      ioctl(audio_fd, SNDCTL_DSP_SAMPLESIZE, &play_precision) == -1 ||
+      ioctl(audio_fd, SNDCTL_DSP_STEREO, &play_stereo) == -1 ||
+      ioctl(audio_fd, SNDCTL_DSP_SPEED, &play_sample_rate) == -1
+    )
+  {
+    perror ("configuration of /dev/dsp failed");
+    exit (1);
+  }
+}
+
+LinuxObuffer::~LinuxObuffer (void)
+{
+  sleep (1);
+  close (audio_fd);
+}
+
+
+void LinuxObuffer::append (uint32 channel, int16 value)
+{
+#ifdef DEBUG
+  if (channel >= channels)
+  {
+    cerr << "illegal channelnumber in LinuxObuffer::append()!\n";
+    exit (1);
+  }
+  if (bufferp[channel] - buffer >= OBUFFERSIZE)
+  {
+    cerr << "buffer overflow!\n";
+    exit (1);
+  }
+#endif
+  *bufferp[channel] = value;
+  bufferp[channel] += channels;
+}
+
+
+void LinuxObuffer::write_buffer (int)
+{
+  int length = (int)((char *)bufferp[0] - (char *)buffer);
+  if (write (audio_fd, buffer, length) != length)
+    cerr << "Warning: couldn't write all samples to /dev/dsp\n";
+  for (int i = 0; i < channels; ++i)
+    bufferp[i] = buffer + i;
+}
+
+bool LinuxObuffer::class_suitable (int channels)
+{
+  if(channels != 1)
+  {
+    cerr << "Stereo output not supported--use mono or stdout\n";
+    return False;
+  }
+  // check for the dsp audio device:
+  audio_fd = open_audio_device ();
+#ifdef DEBUG
+  if (audio_fd != -1)
+    cerr << "Opened Okay!\n";
+  else
+    cerr << "Error: " << errno << "\n";
+#endif
+
+  if (audio_fd != -1)
+    return True;
+  else
+    return False;
+}
+
+#endif	/* LINUX */
 
 #ifdef Indigo
 IndigoObuffer::IndigoObuffer (uint32 number_of_channels, Header *header)
--- ./obuffer.h~	Mon Feb 21 12:28:21 1994
+++ ./obuffer.h	Sat Mar 12 19:12:19 1994
@@ -61,6 +61,25 @@
   void	write_buffer (int fd);
 };
 
+#ifdef LINUX
+class LinuxObuffer : public Obuffer
+{
+  int16 buffer[OBUFFERSIZE];
+  int16 *bufferp[MAXCHANNELS];
+  uint32 channels;
+  static int audio_fd;
+
+	static int open_audio_device(void);
+
+  public:
+	LinuxObuffer (uint32 number_of_channels, Header *);
+       ~LinuxObuffer (void);
+  void	append (uint32 channel, int16 value);
+  void	write_buffer (int dummy);
+	static bool class_suitable(int);
+
+};
+#endif
 
 #ifdef Indigo
 // a class for direct sound output on SGI machines:
----------------------------------END-----------------------------------