From 14e6df5b242c72acc44cf8f68a56ee35dd5c43cf Mon Sep 17 00:00:00 2001 From: "sgunderson@bigfoot.com" <> Date: Mon, 19 Jul 2010 23:18:58 +0200 Subject: [PATCH] Separate the Linux audio functions into a separate file. --- Makefile | 6 ++-- linux_audio.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++ linux_audio.h | 8 +++++ pitch.cpp | 84 ++----------------------------------------------- 4 files changed, 95 insertions(+), 85 deletions(-) create mode 100644 linux_audio.cpp create mode 100644 linux_audio.h diff --git a/Makefile b/Makefile index b98df23..9f3a83f 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,9 @@ CPPFLAGS= all: pitch clean: - $(RM) pitch pitch.o pitchdetector.o + $(RM) pitch pitch.o pitchdetector.o linux_audio.o -pitch: pitch.o pitchdetector.o - $(CXX) -o pitch pitch.o pitchdetector.o -lfftw3 +pitch: pitch.o pitchdetector.o linux_audio.o + $(CXX) -o pitch pitch.o pitchdetector.o linux_audio.o -lfftw3 .PHONY: clean diff --git a/linux_audio.cpp b/linux_audio.cpp new file mode 100644 index 0000000..b76909e --- /dev/null +++ b/linux_audio.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "linux_audio.h" + +int get_dsp_fd(int sample_rate, int fft_length, int overlap) +{ + int fd = open("/dev/dsp", O_RDWR); + if (fd == -1) { + perror("/dev/dsp"); + exit(1); + } + + ioctl(3, SNDCTL_DSP_RESET, 0); + + int fmt = AFMT_S16_LE; // FIXME + ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); + + int chan = 1; + ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan); + + int rate = sample_rate; + ioctl(fd, SOUND_PCM_WRITE_RATE, &rate); + + int max_fragments = 2; + int frag_shift = ffs(fft_length / overlap) - 1; + int fragments = (max_fragments << 16) | frag_shift; + ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragments); + + ioctl(3, SNDCTL_DSP_SYNC, 0); + + return fd; +} + +#if 1 +void read_chunk(int fd, short *in, unsigned num_samples) +{ + int ret; + + ret = read(fd, in, num_samples * sizeof(short)); + if (ret == 0) { + printf("EOF\n"); + exit(0); + } + + if (ret != int(num_samples * sizeof(short))) { + // blah + perror("read"); + exit(1); + } +} +#else +// make a pure 440hz sine for testing +void read_chunk(int fd, short *in, unsigned num_samples) +{ + static double theta = 0.0; + for (unsigned i = 0; i < num_samples; ++i) { + in[i] = 32768.0 * cos(theta); + theta += 2.0 * M_PI * 440.0 / double(SAMPLE_RATE); + } +} +#endif + +void write_sine(int dsp_fd, double freq, unsigned num_samples, unsigned sample_rate) +{ + static double theta = 0.0; + short buf[num_samples]; + + for (unsigned i = 0; i < num_samples; ++i) { + buf[i] = short(cos(theta) * 16384.0); + theta += 2.0 * M_PI * freq / double(sample_rate); + } + + write(dsp_fd, buf, num_samples * sizeof(short)); +} + diff --git a/linux_audio.h b/linux_audio.h new file mode 100644 index 0000000..e26da3d --- /dev/null +++ b/linux_audio.h @@ -0,0 +1,8 @@ +#ifndef _LINUX_AUDIO_H +#define _LINUX_AUDIO_H 1 + +int get_dsp_fd(int sample_rate, int fft_length, int overlap); +void read_chunk(int fd, short *in, unsigned num_samples); +void write_sine(int dsp_fd, double freq, unsigned num_samples, unsigned sample_rate); + +#endif /* !defined(_LINUX_AUDIO_H) */ diff --git a/pitch.cpp b/pitch.cpp index 39e20ce..1ab4696 100644 --- a/pitch.cpp +++ b/pitch.cpp @@ -2,14 +2,8 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include "linux_audio.h" #include "pitchdetector.h" #define BASE_PITCH 440.0 @@ -26,16 +20,13 @@ #define TUNING WELL_TEMPERED_GUITAR -int get_dsp_fd(); -void read_chunk(int fd, short *in, unsigned num_samples); void print_spectrogram(double freq, double amp); void write_sine(int dsp_fd, double freq, unsigned num_samples); int main() { PitchDetector pd(SAMPLE_RATE, FFT_LENGTH, PAD_FACTOR, OVERLAP); - - int fd = get_dsp_fd(); + int fd = get_dsp_fd(SAMPLE_RATE, FFT_LENGTH, OVERLAP); for ( ;; ) { short buf[FFT_LENGTH / PAD_FACTOR / OVERLAP]; @@ -54,77 +45,6 @@ int main() } } -int get_dsp_fd() -{ - int fd = open("/dev/dsp", O_RDWR); - if (fd == -1) { - perror("/dev/dsp"); - exit(1); - } - - ioctl(3, SNDCTL_DSP_RESET, 0); - - int fmt = AFMT_S16_LE; // FIXME - ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); - - int chan = 1; - ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan); - - int rate = SAMPLE_RATE; - ioctl(fd, SOUND_PCM_WRITE_RATE, &rate); - - int max_fragments = 2; - int frag_shift = ffs(FFT_LENGTH / OVERLAP) - 1; - int fragments = (max_fragments << 16) | frag_shift; - ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragments); - - ioctl(3, SNDCTL_DSP_SYNC, 0); - - return fd; -} - -#if 1 -void read_chunk(int fd, short *in, unsigned num_samples) -{ - int ret; - - ret = read(fd, in, num_samples * sizeof(short)); - if (ret == 0) { - printf("EOF\n"); - exit(0); - } - - if (ret != int(num_samples * sizeof(short))) { - // blah - perror("read"); - exit(1); - } -} -#else -// make a pure 440hz sine for testing -void read_chunk(int fd, short *in, unsigned num_samples) -{ - static double theta = 0.0; - for (unsigned i = 0; i < num_samples; ++i) { - in[i] = 32768.0 * cos(theta); - theta += 2.0 * M_PI * 440.0 / double(SAMPLE_RATE); - } -} -#endif - -void write_sine(int dsp_fd, double freq, unsigned num_samples) -{ - static double theta = 0.0; - short buf[num_samples]; - - for (unsigned i = 0; i < num_samples; ++i) { - buf[i] = short(cos(theta) * 16384.0); - theta += 2.0 * M_PI * freq / double(SAMPLE_RATE); - } - - write(dsp_fd, buf, num_samples * sizeof(short)); -} - std::string freq_to_tonename(double freq) { std::string notenames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; -- 2.39.2