diff --git a/src/audio/audiorecord.cpp b/src/audio/audiorecord.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f63803942947e3cac58e91adcab2e76e1a9cf4 --- /dev/null +++ b/src/audio/audiorecord.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "audiorecord.h" + +AudioRecord::AudioRecord(){ + sndSmplRate_ = 44100; + channels_ = 1; + byteCounter_ = 0; + +} + + +void AudioRecord::setSndSamplingRate(int smplRate){ + sndSmplRate_ = smplRate; +} + + +void AudioRecord::openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format) { + + channels_ =1; + fileType_ = type; + byteCounter_ = 0; + sndFormat_ = format; + + bool result = false; + + if(fileType_ == FILE_RAW){ + result = setRawFile( fileName.c_str() ); + } + else if (fileType_ == FILE_WAV){ + result = setWavFile( fileName.c_str() ); + } + +} + + +void AudioRecord::closeFile() { + + if (fp == 0) return; + + if (fileType_ == FILE_RAW) + fclose(fp); + else if (fileType_ == FILE_WAV) + this->closeWavFile(); + +} + + +bool AudioRecord::isOpenFile() { + + if(fp) + return true; + else + return false; +} + + +bool AudioRecord::setRawFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".raw") == NULL) strcat(name, ".raw"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create RAW file: " << name << '.'; + return false; + } + + if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16 + sndFormat_ = INT16; + cout << "AudioRecord: using 16-bit signed integer data format for file " << name << '.'; + } + + cout << "AudioRecord: creating RAW file: " << name; + return true; +} + + +bool AudioRecord::setWavFile(const char *fileName) { + + char name[8192]; + strncpy(name, fileName, 8192); + if ( strstr(name, ".wav") == NULL) strcat(name, ".wav"); + fp = fopen(name, "wb"); + if ( !fp ) { + cout << "AudioRecord: could not create WAV file: " << name; + return false; + } + + struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, + 44100, 0, 2, 16, "dat", 0}; + hdr.riff[3] = 'F'; + hdr.wave[3] = 'E'; + hdr.fmt[3] = ' '; + hdr.data[3] = 'a'; + hdr.num_chans = channels_; + if ( sndFormat_ == INT16 ) { // TODO need to write INT16 to SINT16 + hdr.bits_per_samp = 16; + } + hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8); + hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp); + + + if ( fwrite(&hdr, 4, 11, fp) != 11 ) { + cout << "AudioRecord: could not write WAV header for file " << name << '.'; + return false; + } + + cout << "AudioRecord: creating WAV file: " << name; + return true; +} + + +void AudioRecord::closeWavFile() +{ + int bytes_per_sample = 1; + if ( sndFormat_ == INT16 ) + bytes_per_sample = 2; + + + SINT32 bytes = byteCounter_ * channels_ * bytes_per_sample; + fseek(fp, 40, SEEK_SET); // jump to data length + fwrite(&bytes, 4, 1, fp); + + bytes = byteCounter_ * channels_ * bytes_per_sample + 44; // + 44 for the wave header + fseek(fp, 4, SEEK_SET); // jump to file size + fwrite(&bytes, 4, 1, fp); + fclose( fp ); +} + + +void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) { + + if (fp == 0){ + cout << "AudioRecord: Can't record data, a file has not yet been opened!"; + return; + } + + if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16 + if (nSamples <= 1){ + if ( fwrite(buffer, 2, 1, fp) != 1) + cout << "AudioRecord: Could not record data!"; + } + else { + for ( int k=0; k<nSamples; k++ ) { + cout << "Buffer[" << k << "] : " << buffer[k] << "\n"; + if ( fwrite(&buffer[k], 2, 1, fp) != 1 ) + cout << "AudioRecord: Could not record data!"; + } + } + } + + + + + byteCounter_ += (unsigned long)(sizeof(buffer) / sizeof(SINT16)); + + return; +} + diff --git a/src/audio/audiorecord.h b/src/audio/audiorecord.h new file mode 100644 index 0000000000000000000000000000000000000000..b38eefb29a59be117d896e9c2c6147ff43011ef3 --- /dev/null +++ b/src/audio/audiorecord.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 Savoir-Faire Linux inc. + * Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com> + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <iostream> +#include <string.h> + +#include "global.h" + +using namespace std; + + +// structure for the wave header +struct wavhdr { + char riff[4]; // "RIFF" + SINT32 file_size; // in bytes + char wave[4]; // "WAVE" + char fmt[4]; // "fmt " + SINT32 chunk_size; // in bytes (16 for PCM) + SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law + SINT16 num_chans; // 1=mono, 2=stereo + SINT32 sample_rate; + SINT32 bytes_per_sec; + SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo + SINT16 bits_per_samp; + char data[4]; // "data" + SINT32 data_length; // in bytes +}; + +class AudioRecord +{ + +public: + + AudioRecord(); + + void setSndSamplingRate(int smplRate); + + /** + * Check if no otehr file is opened, then create a new one + * @param fileName A string containing teh file (with/without extension) + * @param type The sound file format (FILE_RAW, FILE_WAVE) + * @param format Internal sound format (INT16 / INT32) + */ + void openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format); + + /** + * Close the opend recording file. If wave: cout the number of byte + */ + void closeFile(); + + /** + * Check if a file is already opened + */ + bool isOpenFile(); + + /** + * Record a chunk of data in an openend file + * @param buffer The data chunk to be recorded + * @param nSamples Number of samples (number of bytes) to be recorded + */ + void recData(SFLDataFormat* buffer, int nSamples); // TODO ad the data to rec + +protected: + + /** + * Set the header for raw files + */ + bool setRawFile(const char* fileName); + + /** + * Set the header for wave files + */ + bool setWavFile(const char* fileName); + + /** + * Compute the number of byte recorded and close the file + */ + void closeWavFile(); + + /** + * Pointer to the recorded file + */ + FILE *fp; //file pointer + + /** + * File format (RAW / WAVE) + */ + FILE_TYPE fileType_; + + /** + * Sound format (SINT16/SINT32) + */ + SOUND_FORMAT sndFormat_; + + /** + * Number of channels + */ + int channels_; + + /** + * Number f byte recorded + */ + unsigned long byteCounter_; + + /** + * Sampling rate + */ + int sndSmplRate_; + +}; diff --git a/src/global.h b/src/global.h index e752d41b2f5ee4be78392cd0dd67308e19bf2b93..259f34e765e479e43b08d0e12ec9e1312e5097f3 100644 --- a/src/global.h +++ b/src/global.h @@ -32,6 +32,19 @@ typedef float float32; typedef short int16; +useful typedefs. +typedef signed short SINT16; +typedef signed int SINT32; + +typedef unsigned long FILE_TYPE; +typedef unsigned long SOUND_FORMAT; + +const FILE_TYPE FILE_RAW = 1; +const FILE_TYPE FILE_WAV = 2; + +static const SOUND_FORMAT INT16 = 0x2; // TODO shold change these symbols +static const SOUND_FORMAT INT32 = 0x8; + #define SUCCESS 0 #define ASSERT( expected , value) if( value == expected ) return SUCCESS; \