diff options
author | jcorgan | 2006-08-03 04:51:51 +0000 |
---|---|---|
committer | jcorgan | 2006-08-03 04:51:51 +0000 |
commit | 5d69a524f81f234b3fbc41d49ba18d6f6886baba (patch) | |
tree | b71312bf7f1e8d10fef0f3ac6f28784065e73e72 /gr-audio-windows | |
download | gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.gz gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.bz2 gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.zip |
Houston, we have a trunk.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gr-audio-windows')
-rw-r--r-- | gr-audio-windows/AUTHORS | 2 | ||||
-rw-r--r-- | gr-audio-windows/ChangeLog | 42 | ||||
-rw-r--r-- | gr-audio-windows/Makefile.am | 24 | ||||
-rw-r--r-- | gr-audio-windows/README | 66 | ||||
-rw-r--r-- | gr-audio-windows/src/Makefile.am | 87 | ||||
-rw-r--r-- | gr-audio-windows/src/audio_windows.i | 68 | ||||
-rw-r--r-- | gr-audio-windows/src/audio_windows_sink.cc | 324 | ||||
-rw-r--r-- | gr-audio-windows/src/audio_windows_sink.h | 83 | ||||
-rw-r--r-- | gr-audio-windows/src/audio_windows_source.cc | 208 | ||||
-rw-r--r-- | gr-audio-windows/src/audio_windows_source.h | 68 | ||||
-rwxr-xr-x | gr-audio-windows/src/qa_audio_windows.py | 40 | ||||
-rwxr-xr-x | gr-audio-windows/src/run_tests.in | 47 |
12 files changed, 1059 insertions, 0 deletions
diff --git a/gr-audio-windows/AUTHORS b/gr-audio-windows/AUTHORS new file mode 100644 index 000000000..a11898d63 --- /dev/null +++ b/gr-audio-windows/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom <eb@comsec.com> +Martin Dvh <nldudok1 at olifantasia com > diff --git a/gr-audio-windows/ChangeLog b/gr-audio-windows/ChangeLog new file mode 100644 index 000000000..3e5ffe024 --- /dev/null +++ b/gr-audio-windows/ChangeLog @@ -0,0 +1,42 @@ +2005-08-09 Eric Blossom <eb@comsec.com> + + * config/gr_python.m4: tweak for cygwin from Andrew Beck. + * src/audio_windows_sink.h: #define NOMINMAX to keep windows from + defining min and max under Cygwin. + +2005-07-23 Stephane Fillod <f8cfe@free.fr> + + * config/gr_libgnuradio_core_extra_ldflags.m4: new + * config/Makefile.am, configure.ac, src/Makefile.am: added + EXTRA_LDFLAGS for --enable-runtime-pseudo-reloc option. + * config/gr_python.m4: update from gnuradio-core + +2005-07-07 Eric Blossom <eb@comsec.com> + + * src/audio_windows_source.cc: reformatted slightly. + +2005-05-12 Martin Dvh <nldudok1 at olifantasia com> + + Initial version based loosely on gr-audio-oss-0.6 + only audio_sink for now (audio_source is empty stub) + +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gr-audio-windows/Makefile.am b/gr-audio-windows/Makefile.am new file mode 100644 index 000000000..ed5e75246 --- /dev/null +++ b/gr-audio-windows/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = src diff --git a/gr-audio-windows/README b/gr-audio-windows/README new file mode 100644 index 000000000..70fbe3ad2 --- /dev/null +++ b/gr-audio-windows/README @@ -0,0 +1,66 @@ + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +gr-audio-windows will add an audio-sink to gnuradio for windows + +Requirements for building: +make sure you have the following installed: +mingw +libtool (recent version ,built yourself, (if needed remove old libtool macros from /usr/share/aclocal)) +msys +python2.4 (just install the prebuild binary for windows) +boost (built yourself, maybe just unpacking the source somewhere will do, we only use header files) +cppunit (built yourself) +gnuradio-core (built with mingw) + +Building: +sources from cvs: +edit bootstrap to your needs (see below for example) +./bootstrap +./configure /configure --with-cppunit-prefix=/whereiscppunit --with-boost-include-dir=/c/whereisboost PYTHON=/c/Python24/python am_cv_python_pythondir=/c/Python24/Lib/site-packages am_cv_python_pyexecdir=/c/Python24/Lib/site-packages +make +make check +make install + + +If you have multiple versions of aclocal then edit bootstrap and change aclocal and automake to the latest version + +You really need a recent libtool to get this built on mingw. +If you build it with default options it will be placed in /usr/local, but the default libtool will still be in /usr. +This will result in old m4 macros will be used by aclocal. +So if you have a more recent libtool installed in /usr/local add -I /usr/local/share/aclocal to the aclocal commandline in bootstrap. +(And add any other directories with the most recent m4 macros) +You could also uninstall (delete) the old libtool macros in /usr/share/aclocal + +bootstrap example: + +!/bin/sh +rm -fr config.cache autom4te*.cache +aclocal-1.8 -I /usr/local/share/aclocal -I config +autoconf +autoheader +libtoolize --automake +automake-1.8 --add-missing + + +configuration example: +./configure --with-cppunit-prefix=/usr/local --with-boost-include-dir=/d/boost_1_32_0/include/boost-1_32 PYTHON=/d/Python24/python am_cv_python_pythondir=/d/Python24/Lib/site-packages am_cv_python_pyexecdir=/d/Python24/Lib/site-packages + +Martin Dvh, juli 2005 diff --git a/gr-audio-windows/src/Makefile.am b/gr-audio-windows/src/Makefile.am new file mode 100644 index 000000000..3d9446d3e --- /dev/null +++ b/gr-audio-windows/src/Makefile.am @@ -0,0 +1,87 @@ +# +# Copyright 2004,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the gnuradio.audio_windows module +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +EXTRA_DIST = run_tests.in +TESTS = run_tests + +LOCAL_IFILES = \ + audio_windows.i + +NON_LOCAL_IFILES = \ + $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +BUILT_SOURCES = \ + audio_windows.cc \ + audio_windows.py + +ourpython_PYTHON = \ + audio_windows.py + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) + +SWIGCPPPYTHONARGS = -python $(PYTHON_CPPFLAGS) \ + -I$(swigincludedir) -I$(grincludedir) + +ourlib_LTLIBRARIES = _audio_windows.la + +_audio_windows_la_SOURCES = \ + audio_windows.cc \ + audio_windows_sink.cc \ + audio_windows_source.cc + + +grinclude_HEADERS = \ + audio_windows_sink.h \ + audio_windows_source.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +_audio_windows_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + $(GNURADIO_CORE_LIBS) \ + -lwinmm \ + -lstdc++ + +_audio_windows_la_LDFLAGS = -no-undefined -module -avoid-version \ + $(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +audio_windows.cc audio_windows.py: audio_windows.i + $(SWIG) $(SWIGCPPPYTHONARGS) -module audio_windows -o audio_windows.cc $< + + +noinst_PYTHON = qa_audio_windows.py + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc diff --git a/gr-audio-windows/src/audio_windows.i b/gr-audio-windows/src/audio_windows.i new file mode 100644 index 000000000..99e9e43a2 --- /dev/null +++ b/gr-audio-windows/src/audio_windows.i @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%feature("autodoc","1"); + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include "audio_windows_sink.h" +#include "audio_windows_source.h" +#include <stdexcept> +%} + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_windows,sink) + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + + +class audio_windows_sink : public gr_sync_block { + protected: + audio_windows_sink (int sampling_freq, const std::string device_name = ""); + + public: + ~audio_windows_sink (); +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(audio_windows,source) + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, + const std::string dev = "" + ) throw (std::runtime_error); + +class audio_windows_source : public gr_sync_block { + protected: + audio_windows_source (int sampling_freq, const std::string device_name = ""); + + public: + ~audio_windows_source (); +}; diff --git a/gr-audio-windows/src/audio_windows_sink.cc b/gr-audio-windows/src/audio_windows_sink.cc new file mode 100644 index 000000000..ff1d19cdc --- /dev/null +++ b/gr-audio-windows/src/audio_windows_sink.cc @@ -0,0 +1,324 @@ +/* -*- c++ -*- */ +/* +* Copyright 2004 Free Software Foundation, Inc. +* +* This file is part of GNU Radio +* +* GNU Radio 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, or (at your option) +* any later version. +* +* GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <audio_windows_sink.h> +#include <gr_io_signature.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <iostream> +#include <stdexcept> +#include <string> +#include <sstream> + +static const double CHUNK_TIME = 0.1; //0.001; // 100 ms + +// FIXME these should query some kind of user preference + +static std::string +default_device_name () +{ + return "WAVE_MAPPER"; +} + +audio_windows_sink::audio_windows_sink (int sampling_freq, const std::string device_name) + : gr_sync_block ("audio_windows_sink", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (0, 0, 0)), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty ()? default_device_name () : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + d_wave_write_event = CreateEvent (NULL, FALSE, FALSE, NULL); + if (open_waveout_device () < 0) + { + //fprintf (stderr, "audio_windows_sink:open_waveout_device() failed\n"); + perror ("audio_windows_sink:open_waveout_device( ) failed\n"); + throw + std::runtime_error ("audio_windows_sink:open_waveout_device() failed"); + } + + d_chunk_size = (int) (d_sampling_freq * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short[d_chunk_size * 2]; + +} + +audio_windows_sink::~audio_windows_sink () +{ + /* Free the callback Event */ + CloseHandle (d_wave_write_event); + waveOutClose (d_h_waveout); + delete[]d_buffer; +} + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, const std::string dev) +{ + return audio_windows_sink_sptr (new + audio_windows_sink (sampling_freq, dev)); +} + + +int +audio_windows_sink::work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items) +{ + const float *f0, *f1; + bool playtestsound = false; + if (playtestsound) + { + // dummy + + f0 = (const float *) input_items[0]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (sin (2.0 * 3.1415926535897932384626 * (float) j * 1000.0 / (float) d_sampling_freq) * 8192 + 0); //+32767 + d_buffer[2 * j + 1] = d_buffer[2 * j + 0]; + } + f0 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + // break; + } + else + { + switch (input_items.size ()) + { + + case 1: // mono input + + f0 = (const float *) input_items[0]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (f0[j] * 32767); + d_buffer[2 * j + 1] = (short) (f0[j] * 32767); + } + f0 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + //fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + break; + + case 2: // stereo input + + f0 = (const float *) input_items[0]; + f1 = (const float *) input_items[1]; + + for (int i = 0; i < noutput_items; i += d_chunk_size) + { + for (int j = 0; j < d_chunk_size; j++) + { + d_buffer[2 * j + 0] = (short) (f0[j] * 32767); + d_buffer[2 * j + 1] = (short) (f1[j] * 32767); + } + f0 += d_chunk_size; + f1 += d_chunk_size; + if (write_waveout + ((HPSTR) d_buffer, 2 * d_chunk_size * sizeof (short)) < 0) + { + //fprintf (stderr, "audio_windows_sink: write failed\n"); + perror ("audio_windows_sink: write failed"); + } + } + break; + } + } + return noutput_items; +} + +int +audio_windows_sink::string_to_int (const std::string & s) +{ + int i; + std::istringstream (s) >> i; + return i; +} //ToInt() + +int +audio_windows_sink::open_waveout_device (void) +{ + + UINT /*UINT_PTR */ u_device_id; + /** Identifier of the waveform-audio output device to open. It can be either a device identifier or a handle of an open waveform-audio input device. You can use the following flag instead of a device identifier. + * + * Value Meaning + * WAVE_MAPPER The function selects a waveform-audio output device capable of playing the given format. + */ + if (d_device_name.empty () || default_device_name () == d_device_name) + u_device_id = WAVE_MAPPER; + else + u_device_id = (UINT) string_to_int (d_device_name); + // Open a waveform device for output using event callback. + + unsigned long result; + //HWAVEOUT outHandle; + WAVEFORMATEX wave_format; + + /* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */ + wave_format.wFormatTag = WAVE_FORMAT_PCM; + wave_format.nChannels = 2; + wave_format.nSamplesPerSec = d_sampling_freq; //44100; + wave_format.wBitsPerSample = 16; + wave_format.nBlockAlign = + wave_format.nChannels * (wave_format.wBitsPerSample / 8); + wave_format.nAvgBytesPerSec = + wave_format.nSamplesPerSec * wave_format.nBlockAlign; + wave_format.cbSize = 0; + + /* Open the (preferred) Digital Audio Out device. */ + result = waveOutOpen (&d_h_waveout, WAVE_MAPPER, &wave_format, (DWORD_PTR) d_wave_write_event, 0, CALLBACK_EVENT | WAVE_ALLOWSYNC); //|WAVE_FORMAT_DIRECT | CALLBACK_EVENT| WAVE_ALLOWSYNC + if (result) + { + fprintf (stderr, + "audio_windows_sink: Failed to open waveform output device.\n"); + perror ("audio_windows_sink: Failed to open waveform output device."); + //LocalUnlock(hFormat); + //LocalFree(hFormat); + //mmioClose(hmmio, 0); + return -1; + } + + // + // Do not Swallow the "open" event. + // + //WaitForSingleObject(d_wave_write_event, INFINITE); + + // Allocate and lock memory for the header. + + d_h_wave_hdr = GlobalAlloc (GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof (WAVEHDR)); + if (d_h_wave_hdr == NULL) + { + //GlobalUnlock(hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Not enough memory for header.\n"); + perror ("audio_windows_sink: Not enough memory for header."); + return -1; + } + + d_lp_wave_hdr = (LPWAVEHDR) GlobalLock (d_h_wave_hdr); + if (d_lp_wave_hdr == NULL) + { + //GlobalUnlock(hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to lock memory for header.\n"); + perror ("audio_windows_sink: Failed to lock memory for header."); + return -1; + } + //d_lp_wave_hdr->dwFlags = WHDR_DONE; + return 0; +} + +int +audio_windows_sink::write_waveout (HPSTR lp_data, DWORD dw_data_size) +{ + UINT w_result; + int teller = 100; + // After allocation, set up and prepare header. + /*while ((d_lp_wave_hdr->dwFlags & WHDR_DONE)==0 && teller>0) + { + teller--; + Sleep(1); + } */ + // Wait until previous wave write completes (first event is the open event). + WaitForSingleObject (d_wave_write_event, 100); //INFINITE + d_lp_wave_hdr->lpData = lp_data; + d_lp_wave_hdr->dwBufferLength = dw_data_size; + d_lp_wave_hdr->dwFlags = 0L; + /* Clear the WHDR_DONE bit (which the driver set last time that + this WAVEHDR was sent via waveOutWrite and was played). Some + drivers need this to be cleared */ + //d_lp_wave_hdr->dwFlags &= ~WHDR_DONE; + + d_lp_wave_hdr->dwLoops = 0L; + w_result = + waveOutPrepareHeader (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + if (w_result != 0) + { + //GlobalUnlock( hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to waveOutPrepareHeader. error %i\n",w_result); + perror ("audio_windows_sink: Failed to waveOutPrepareHeader"); + } + // Now the data block can be sent to the output device. The + // waveOutWrite function returns immediately and waveform + // data is sent to the output device in the background. + //while (! readyforplayback) Sleep(1); + //readyforplayback=false; + // + // + + w_result = waveOutWrite (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + if (w_result != 0) + { + //GlobalUnlock( hData); + //GlobalFree(hData); + //fprintf (stderr, "audio_windows_sink: Failed to write block to device.error %i\n",w_result); + perror ("audio_windows_sink: Failed to write block to device"); + switch (w_result) + { + case MMSYSERR_INVALHANDLE: + fprintf (stderr, "Specified device handle is invalid. \n"); + break; + case MMSYSERR_NODRIVER: + fprintf (stderr, " No device driver is present. \n"); + break; + case MMSYSERR_NOMEM: + fprintf (stderr, " Unable to allocate or lock memory. \n"); + break; + case WAVERR_UNPREPARED: + fprintf (stderr, + " The data block pointed to by the pwh parameter hasn't been prepared. \n"); + break; + default: + fprintf (stderr, "Unknown error %i\n", w_result); + } + waveOutUnprepareHeader (d_h_waveout, d_lp_wave_hdr, sizeof (WAVEHDR)); + return -1; + } + // WaitForSingleObject(d_wave_write_event, INFINITE); + return 0; +} diff --git a/gr-audio-windows/src/audio_windows_sink.h b/gr-audio-windows/src/audio_windows_sink.h new file mode 100644 index 000000000..0d7e630da --- /dev/null +++ b/gr-audio-windows/src/audio_windows_sink.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_WINDOWS_SINK_H +#define INCLUDED_AUDIO_WINDOWS_SINK_H + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX // stops windef.h defining max/min under cygwin + +#include <windows.h> +#include <mmsystem.h> + +#include <gr_sync_block.h> +#include <string> + + +class audio_windows_sink; +typedef boost::shared_ptr <audio_windows_sink> audio_windows_sink_sptr; + +audio_windows_sink_sptr +audio_windows_make_sink (int sampling_freq, const std::string dev = ""); + +/*! + * \brief audio sink using winmm mmsystem (win32 only) + * + * input signature is one or two streams of floats. + * Input samples must be in the range [-1,1]. + */ + +class audio_windows_sink : public gr_sync_block +{ + friend + audio_windows_sink_sptr + audio_windows_make_sink (int sampling_freq, const std::string device_name); + + int d_sampling_freq; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + HWAVEOUT d_h_waveout; + HGLOBAL d_h_wave_hdr; + LPWAVEHDR d_lp_wave_hdr; + HANDLE d_wave_write_event; + +protected: + int + string_to_int (const std::string & s); + audio_windows_sink (int sampling_freq, const std::string device_name = ""); + int + open_waveout_device (void); + int + write_waveout (HPSTR lp_data, DWORD dw_data_size); + +public: + ~audio_windows_sink (); + + int + work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items); +}; + +#endif /* INCLUDED_AUDIO_WINDOWS_SINK_H */ diff --git a/gr-audio-windows/src/audio_windows_source.cc b/gr-audio-windows/src/audio_windows_source.cc new file mode 100644 index 000000000..8879e3b2d --- /dev/null +++ b/gr-audio-windows/src/audio_windows_source.cc @@ -0,0 +1,208 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <audio_windows_source.h> +#include <gr_io_signature.h> +//include <sys/soundcard.h> +//include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <iostream> +#include <stdexcept> + + +static const double CHUNK_TIME = 0.005; // 5 ms + +// FIXME these should query some kind of user preference + +static std::string +default_device_name () +{ + return "/dev/dsp"; +} + +audio_windows_source::audio_windows_source (int sampling_freq, const std::string device_name) + : gr_sync_block ("audio_windows_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 2, sizeof (float))), + d_sampling_freq (sampling_freq), + d_device_name (device_name.empty ()? default_device_name () : device_name), + d_fd (-1), d_buffer (0), d_chunk_size (0) +{ + //FIXME TODO implement me +#if 0 + if ((d_fd = open (d_device_name.c_str (), O_RDONLY)) < 0) + { + fprintf (stderr, "audio_windows_source: "); + perror (d_device_name.c_str ()); + throw + std::runtime_error ("audio_windows_source"); + } + + d_chunk_size = (int) (d_sampling_freq * CHUNK_TIME); + set_output_multiple (d_chunk_size); + + d_buffer = new short[d_chunk_size * 2]; + + int format = AFMT_S16_NE; + int orig_format = format; + if (ioctl (d_fd, SNDCTL_DSP_SETFMT, &format) < 0) + { + std:: + cerr << "audio_windows_source: " << d_device_name << + " ioctl failed\n"; + perror (d_device_name.c_str ()); + throw + std::runtime_error ("audio_windows_source"); + } + + if (format != orig_format) + { + fprintf (stderr, "audio_windows_source: unable to support format %d\n", + orig_format); + fprintf (stderr, " card requested %d instead.\n", format); + } + + // set to stereo no matter what. Some hardware only does stereo + int channels = 2; + if (ioctl (d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) + { + perror ("audio_windows_source: could not set STEREO mode"); + throw + std::runtime_error ("audio_windows_source"); + } + + // set sampling freq + int sf = sampling_freq; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0) + { + std::cerr << "audio_windows_source: " + << d_device_name << ": invalid sampling_freq " + << sampling_freq << "\n"; + sampling_freq = 8000; + if (ioctl (d_fd, SNDCTL_DSP_SPEED, &sf) < 0) + { + std:: + cerr << + "audio_windows_source: failed to set sampling_freq to 8000\n"; + throw + std::runtime_error ("audio_windows_source"); + } + } +#endif +} + +audio_windows_source::~audio_windows_source () +{ + /*close (d_fd); + delete [] d_buffer; + */ +} + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, const std::string dev) +{ + return audio_windows_source_sptr (new + audio_windows_source (sampling_freq, + dev)); +} + + +int +audio_windows_source::work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items) +{ + //FIXME TODO implement me +#if 0 + float *f0 = (float *) output_items[0]; + float *f1 = (float *) output_items[1]; // will be invalid if this is mono output + + const int shorts_per_item = 2; // L + R + const int bytes_per_item = shorts_per_item * sizeof (short); + + // To minimize latency, never return more than CHUNK_TIME + // worth of samples per call to work. + // FIXME, we need an API to set this value + + noutput_items = std::min (noutput_items, d_chunk_size); + + int base = 0; + int ntogo = noutput_items; + + while (ntogo > 0) + { + int nbytes = std::min (ntogo, d_chunk_size) * bytes_per_item; + int result_nbytes = read (d_fd, d_buffer, nbytes); + + if (result_nbytes < 0) + { + perror ("audio_windows_source"); + return -1; // say we're done + } + + if ((result_nbytes & (bytes_per_item - 1)) != 0) + { + fprintf (stderr, "audio_windows_source: internal error.\n"); + throw std::runtime_error ("internal error"); + } + + int result_nitems = result_nbytes / bytes_per_item; + + // now unpack samples into output streams + + switch (output_items.size ()) + { + case 1: // mono output + for (int i = 0; i < result_nitems; i++) + { + f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767); + } + break; + + case 2: // stereo output + for (int i = 0; i < result_nitems; i++) + { + f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767); + f1[base + i] = d_buffer[2 * i + 1] * (1.0 / 32767); + } + break; + + default: + assert (0); + } + + ntogo -= result_nitems; + base += result_nitems; + } + + return noutput_items - ntogo; +#endif + return -1; // EOF +} diff --git a/gr-audio-windows/src/audio_windows_source.h b/gr-audio-windows/src/audio_windows_source.h new file mode 100644 index 000000000..718ac2f9c --- /dev/null +++ b/gr-audio-windows/src/audio_windows_source.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_AUDIO_WINDOWS_SOURCE_H +#define INCLUDED_AUDIO_WINDOWS_SOURCE_H + +#include <gr_sync_block.h> +#include <string> + + +class audio_windows_source; +typedef boost::shared_ptr <audio_windows_source> audio_windows_source_sptr; + +audio_windows_source_sptr +audio_windows_make_source (int sampling_freq, const std::string dev = ""); + +/*! + * \brief audio source using winmm mmsystem (win32 only) + * + * Output signature is one or two streams of floats. + * Output samples will be in the range [-1,1]. + */ + +class audio_windows_source : public gr_sync_block +{ + friend + audio_windows_source_sptr + audio_windows_make_source (int sampling_freq, + const std::string device_name); + + int d_sampling_freq; + std::string d_device_name; + int d_fd; + short *d_buffer; + int d_chunk_size; + +protected: + audio_windows_source (int sampling_freq, const std::string device_name = ""); + +public: + ~audio_windows_source (); + + int + work (int noutput_items, + gr_vector_const_void_star & input_items, + gr_vector_void_star & output_items); +}; + +#endif /* INCLUDED_AUDIO_WINDOWS_SOURCE_H */ diff --git a/gr-audio-windows/src/qa_audio_windows.py b/gr-audio-windows/src/qa_audio_windows.py new file mode 100755 index 000000000..e7663a8b5 --- /dev/null +++ b/gr-audio-windows/src/qa_audio_windows.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from gnuradio import gr, gr_unittest +import audio_windows + +class qa_oss (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have audio drivers, soundcard, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gr-audio-windows/src/run_tests.in b/gr-audio-windows/src/run_tests.in new file mode 100755 index 000000000..6eb596383 --- /dev/null +++ b/gr-audio-windows/src/run_tests.in @@ -0,0 +1,47 @@ +#!/bin/sh + +# All this strange PYTHONPATH manipulation is required to run our +# tests using our just built shared library and swig-generated python +# code prior to installation. + +# build tree == src tree unless you're doing a VPATH build. +# If you don't know what a VPATH build is, you're not doing one. Relax... + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +# Where to look in the build tree for our shared library +libbld=@abs_top_builddir@/gr-audio-windows/src +# Where to look in the src tree for swig generated python code +libsrc=@abs_top_srcdir@/gr-audio-windows/src +# Where to look in the src tree for hand written python code +py=@abs_top_srcdir@/gr-audio-windows/src + +# Where to look for GNU Radio python modules in current build tree +# FIXME this is wrong on a distcheck. We really need to ask gnuradio-core +# where it put its python files. +grpythonbld=@abs_top_builddir@/gnuradio-core/src/python/:@abs_top_builddir@/gnuradio-core/src/lib/swig/:@abs_top_builddir@/gnuradio-core/src/lib/swig/.libs + +PYTHONPATH="$grpythonbld:$libbld:$libbld/.libs:$libsrc:$py:$PYTHONPATH" +export PYTHONPATH + +# +# This is the simple part... +# Run everything that matches qa_*.py and return the final result. +# + +ok=yes +for file in @srcdir@/qa_*.py +do + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi |