X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=wdq2wav.cpp;h=60e58421c9a60554674abc11df48f2987b98d085;hb=746abe47c4eaefae0023dde9a8938b80bfcb8247;hp=e307f00c5f757e52e465d8958b2faa072609bf92;hpb=8eec8116b49d2838727bd77a75308c6a65aaf2e7;p=wdq2wav.git diff --git a/wdq2wav.cpp b/wdq2wav.cpp index e307f00..60e5842 100644 --- a/wdq2wav.cpp +++ b/wdq2wav.cpp @@ -8,7 +8,7 @@ ** ** Copyright (c) 2003 Kevin Rosenberg ** -** $Id: wdq2wav.cpp,v 1.10 2003/01/21 11:23:09 kevin Exp $ +** $Id: wdq2wav.cpp,v 1.19 2003/02/24 12:53:46 kevin Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License (version 2) as @@ -26,11 +26,36 @@ #include -const char* g_szIdStr = "$Id: wdq2wav.cpp,v 1.10 2003/01/21 11:23:09 kevin Exp $"; +const char* g_szIdStr = "$Id: wdq2wav.cpp,v 1.19 2003/02/24 12:53:46 kevin Exp $"; bool g_quiet = false; bool g_verbose = false; bool g_debug = false; +bool g_ignore_zero = false; + + +#ifdef WIN32 +#define lseek _lseek +#define close _close +#define open _open +#define read _read +#define write _write +#define O_BINARY _O_BINARY +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_RDWR _O_RDRW +#define O_TRUNC _O_TRUNC +#define O_CREAT _O_CREAT +const int g_fileMode = _S_IWRITE | _S_IREAD; +struct fpos_t std::_Fpz = {0,0}; +#else +const int g_fileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; +// Define as NULL for non-Windows platforms +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#endif + void error_msg (const char *msg) @@ -60,7 +85,7 @@ fileBasename (const char* filename) char * str_rm_tail (char *str, const char* const charlist) { - int i; + size_t i; for (i = strlen(str) - 1; i >= 0; i--) if (strchr (charlist, str[i]) != NULL) @@ -83,12 +108,13 @@ usage (const char* progname) { std::cout << "usage: " << fileBasename (progname) << " [OPTIONS] \n"; std::cout << "OPTIONS\n"; - std::cout << " -p Play channel through audio system\n"; - std::cout << " -q Supress all messages\n"; - std::cout << " -v Verbose mode\n"; - std::cout << " -d Debug mode\n"; - std::cout << " -r Print program version\n"; - std::cout << " -h Print this help message\n"; + std::cout << " -p Play channel through audio system\n"; + std::cout << " -q Supress all messages\n"; + std::cout << " -z Scale output without regard for windaq zero point\n"; + std::cout << " -v Verbose mode\n"; + std::cout << " -d Debug mode\n"; + std::cout << " -r Print program version\n"; + std::cout << " -h Print this help message\n"; } @@ -98,7 +124,9 @@ main (int argc, char *argv[]) int c; bool play = false; - while ((c = getopt (argc, argv, "rqvdph")) != -1) { + const char* progname = argv[0]; + + while ((c = getopt (argc, argv, "rqvzdph")) != -1) { switch (c) { case 'r': std::cout << "Version " << g_szIdStr << std::endl; @@ -115,12 +143,15 @@ main (int argc, char *argv[]) case 'p': play = true; break; + case 'z': + g_ignore_zero = true; + break; case 'h': - usage (argv[0]); + usage (progname); return (0); case '?': default: - usage(argv[0]); + usage (progname); return (1); } } @@ -128,13 +159,13 @@ main (int argc, char *argv[]) argv += optind; if (argc > 3) { std::cerr << "Too many parameters\n"; - usage (argv[0]); + usage (progname); return (1); } char wdq_fname[MAX_INPUT_STR]; if (argc >= 1) - strncpy (wdq_fname, argv [1], MAX_INPUT_STR); + strncpy (wdq_fname, argv [0], MAX_INPUT_STR); else { std::cout << "Enter input WinDAQ filename: "; std::cin.getline (wdq_fname, MAX_INPUT_STR); @@ -142,7 +173,7 @@ main (int argc, char *argv[]) char channel_buf [MAX_INPUT_STR]; if (argc >= 2) - strncpy (channel_buf, argv[2], MAX_INPUT_STR); + strncpy (channel_buf, argv[1], MAX_INPUT_STR); else { std::cout << "Enter channel number: "; std::cin.getline (channel_buf, MAX_INPUT_STR); @@ -154,26 +185,26 @@ main (int argc, char *argv[]) std::ostringstream os; os << "Error: Channel " << channel_buf << " is not an integer"; error_msg (os.str().c_str()); - usage (argv[0]); + usage (progname); return (1); } char wav_fname[MAX_INPUT_STR]; if (argc >= 3) - strncpy (wav_fname, argv[3], MAX_INPUT_STR); + strncpy (wav_fname, argv[2], MAX_INPUT_STR); else { std::cout << "Enter output wav filename: "; std::cin.getline (wav_fname, MAX_INPUT_STR); } - if (! wdq2wav (wdq_fname, channel, wav_fname)) + if (! wdq2wav (wdq_fname, channel, wav_fname, play)) return 1; return 0; } bool -wdq2wav (const char* wdq_fname, const int channel, const char *wav_fname) +wdq2wav (const char* wdq_fname, const int channel, const char *wav_fname, bool play) { WindaqFile wdq (wdq_fname); @@ -228,6 +259,7 @@ wdq2wav (const char* wdq_fname, const int channel, const char *wav_fname) ", maximum: " << wdq_channel.m_max_raw_data; info_msg (os3.str().c_str()); } + if (g_debug) { std::ostringstream os4; os4 << " Scaled minimum: " << wdq_channel.m_min_scaled_data << @@ -251,12 +283,15 @@ wdq2wav (const char* wdq_fname, const int channel, const char *wav_fname) return false; } + if (play) + wav.Play(); + return true; } WindaqFile::WindaqFile (const char* fname) - : m_fd(0), m_nChannels(0), m_nSamples(0), m_sample_rate(0), m_valid(false), + : m_valid(false), m_fd(0), m_nChannels(0), m_nSamples(0), m_sample_rate(0), m_strFile (fname) { } @@ -276,7 +311,9 @@ bool read_int2 (int fd, unsigned short int& n) tmp2 = tmp1; if (read (fd, &tmp1, 1) != 1) return false; + n = tmp2 + (tmp1 * 256); + return true; } bool read_int4 (int fd, unsigned int& n) @@ -288,7 +325,9 @@ bool read_int4 (int fd, unsigned int& n) tmp4 = tmp2; if (! read_int2 (fd, tmp2)) return false; + n = tmp4 + (tmp2 * 65536); + return true; } bool @@ -297,7 +336,7 @@ WindaqFile::ReadHeader () unsigned short int tmp2; m_valid = false; - if ((m_fd = open (m_strFile.c_str(), O_RDONLY)) < 0) { + if ((m_fd = open (m_strFile.c_str(), O_RDONLY | O_BINARY)) < 0) { m_error = "Unable to open file"; return false; } @@ -359,8 +398,8 @@ WindaqChannel::WindaqChannel (WindaqFile& wdq, const int channel) { if (wdq.m_valid) { if (channel >= 1 && channel <= wdq.m_nChannels) { - m_valid = true; - read_channel_data(); + if (read_channel_data()) + m_valid = true; } else { std::ostringstream os; os << "Channel " << channel << " is invalid, valid range 1-" << @@ -382,7 +421,7 @@ bool get_float8 (int fd, double& f) if (read (fd, &buf, 8) != 8) return false; -#ifdef BIG_ENDIAN +#if WORDS_BIG_ENDIAN unsigned char c; c = buf[0]; buf[0] = buf[7]; buf[7] = c; c = buf[1]; buf[1] = buf[6]; buf[6] = c; @@ -390,22 +429,16 @@ bool get_float8 (int fd, double& f) c = buf[3]; buf[3] = buf[4]; buf[4] = c; #endif - double* p = reinterpret_cast(buf); - f = *p; + f = *(reinterpret_cast(buf)); + + return true; } bool WindaqChannel::read_channel_data () { - unsigned short int tmp2; - unsigned int tmp4; - double float8; - int fd = r_wdq.m_fd; - if (! m_valid) - return false; - m_data = new signed short int [r_wdq.m_nSamples * 2]; lseek (fd, r_wdq.m_channel_offset + 8 + @@ -414,7 +447,7 @@ WindaqChannel::read_channel_data () if (! get_float8 (fd, m_slope)) return false; - if (get_float8 (fd, m_intercept)) + if (! get_float8 (fd, m_intercept)) return false; char units[7]; @@ -426,23 +459,24 @@ WindaqChannel::read_channel_data () m_units = units; unsigned int row_bytes = 2 * r_wdq.m_nChannels; - signed short int sample_row [row_bytes]; + signed short int *sample_row = new signed short int [row_bytes]; signed short int* psample = &sample_row[m_channel - 1]; lseek (fd, r_wdq.m_nHeader_bytes, SEEK_SET); - long int i; - signed short int data_max, data_min; + unsigned long int i; + signed short int data_max = 0, data_min = 0; for (i = 0; i < r_wdq.m_nSamples; i++) { if (read (fd, sample_row, row_bytes) != row_bytes) { std::ostringstream os; os << "Error reading file at " << i; error_msg (os.str().c_str()); + delete sample_row; return false; } signed short int v = *psample; -#ifdef BIG_ENDIAN +#if WORDS_BIG_ENDIAN unsigned char* p = reinterpret_cast(&v); unsigned char c = p[0]; p[0] = p[1]; p[1] = c; #endif @@ -466,6 +500,7 @@ WindaqChannel::read_channel_data () m_max_scaled_data = (m_slope * data_max) + m_intercept; m_min_scaled_data = (m_slope * data_min) + m_intercept; + delete sample_row; return true; } @@ -479,12 +514,20 @@ WavFile::WavFile (WindaqChannel& wdq_channel, const char* fname) m_nBitsPerSample = 16; m_nBytesPerSample = 2; m_rate = wdq_channel.r_wdq.m_sample_rate; - - double data_offset = -wdq_channel.m_min_scaled_data; - double data_scale = 0.; - if (wdq_channel.m_max_scaled_data != wdq_channel.m_min_scaled_data) - data_scale = 65535. / (wdq_channel.m_max_scaled_data - - wdq_channel.m_min_scaled_data); + + double data_offset = 0, data_scale = 0; + if (g_ignore_zero) { + data_offset = -wdq_channel.m_min_scaled_data; + if (wdq_channel.m_max_scaled_data != wdq_channel.m_min_scaled_data) + data_scale = 65535. / (wdq_channel.m_max_scaled_data - + wdq_channel.m_min_scaled_data); + } else { + double max_value = fabs(wdq_channel.m_max_scaled_data); + if (fabs (wdq_channel.m_min_scaled_data) > max_value) + max_value = fabs (wdq_channel.m_min_scaled_data); + if (max_value != 0.) + data_scale = 32767. / max_value; + } if (g_debug) { std::ostringstream os; @@ -492,10 +535,11 @@ WavFile::WavFile (WindaqChannel& wdq_channel, const char* fname) info_msg (os.str().c_str()); } - unsigned int nHeaderBytes = 44; - m_nFileBytes = nHeaderBytes + m_nSamples * m_nBytesPerSample; + m_nHeaderBytes = 44; + m_nDataBytes = m_nSamples * m_nBytesPerSample * m_nChannels; + m_nFileBytes = m_nHeaderBytes + m_nDataBytes; - unsigned int nHeaderShortInts = nHeaderBytes / sizeof(signed short int); + unsigned int nHeaderShortInts = m_nHeaderBytes / sizeof(signed short int); m_data = new signed short int [m_nSamples + nHeaderShortInts]; signed short int* input = wdq_channel.m_data; @@ -506,14 +550,18 @@ WavFile::WavFile (WindaqChannel& wdq_channel, const char* fname) if (! fill_header ()) return; - long int i; + unsigned long int i; for (i = 0; i < m_nSamples; i++) { double value = input[i]; value = (slope * value) + intercept; - value = (value + data_offset) * data_scale; - value += 0.5 - 32768; + if (g_ignore_zero) { + value = (value + data_offset) * data_scale; + value += 0.5 - 32768; + } else + value = value * data_scale; + signed short int v = static_cast(value); -#ifdef BIG_ENDIAN +#if WORDS_BIG_ENDIAN unsigned char* p = reinterpret_cast(&v); unsigned char c = p[0]; p[0] = p[1]; p[1] = c; #endif @@ -554,12 +602,11 @@ bool WavFile::fill_header () { char* pData = reinterpret_cast (m_data); - unsigned long data_bytes = m_nSamples * m_nBytesPerSample * m_nChannels; strncpy (pData, "RIFF", 4); // Length of file after 8 byte header - put_int4 (pData + 4, 36 + data_bytes); + put_int4 (pData + 4, 36 + m_nDataBytes); strncpy (pData + 8, "WAVEfmt ", 8); @@ -586,7 +633,7 @@ WavFile::fill_header () strncpy (pData + 36, "data", 4); - put_int4 (pData + 40, data_bytes); + put_int4 (pData + 40, m_nDataBytes); return true; } @@ -594,15 +641,11 @@ WavFile::fill_header () bool WavFile::WriteFile () { - unsigned short int tmp2; - unsigned int tmp4; - if (! m_valid) return false; if (m_fd == 0) - if ((m_fd = open (m_strFile.c_str(), O_WRONLY | O_TRUNC | O_CREAT, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == 0) { + if ((m_fd = open (m_strFile.c_str(), O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, g_fileMode)) == 0) { std::ostringstream os; os << "Error opening output file " << m_strFile.c_str(); error_msg (os.str().c_str()); @@ -622,6 +665,70 @@ WavFile::WriteFile () return true; } +#ifdef WIN32 +#include +#include +#elif defined(LINUX) +#include +#include +#endif + +bool +WavFile::Play () +{ +#ifdef WIN32 + if (PlaySound ((LPCSTR) m_data, 0, SND_MEMORY | SND_NODEFAULT)) + return true; +#elif defined(LINUX) + int fd; + if ((fd = open ("/dev/dsp",O_WRONLY)) == -1) { + error_msg ("Error opening /dev/dsp"); + return false; + } + + int format = AFMT_S16_LE; + if (ioctl (fd, SNDCTL_DSP_SETFMT, &format) == -1) { + error_msg ("Error setting DSP format"); + close(fd); return false; + } + if (format != AFMT_S16_LE) { + error_msg ("DSP Format not set"); + close(fd); return false; + } + + int channels = m_nChannels; + if (ioctl (fd, SNDCTL_DSP_CHANNELS, &format) == -1) { + error_msg ("Error setting number of channels"); + close(fd); return false; + } + if (channels != m_nChannels) { + error_msg ("Number of channels not set"); + close(fd); return false; + } + + unsigned int speed = static_cast(m_rate + 0.5); + if (ioctl (fd, SNDCTL_DSP_SPEED, &speed) == -1) { + error_msg ("Error setting sample rate"); + close(fd); return false; + } + if (speed != m_rate && ! g_quiet) { + std::ostringstream os; + os << "Warning: Sample rate set to " << speed << ", not " << m_rate; + error_msg (os.str().c_str()); + } + + if (write (fd, reinterpret_cast(m_data) + m_nHeaderBytes, m_nDataBytes) != + m_nDataBytes) { + error_msg ("Error writing audio samples"); + close(fd); return false; + } + close (fd); + return true; +#else +#endif + return false; +} +