Commit e0527b19 authored by alexandresavard's avatar alexandresavard

Open/close a wave file when pulse audio stream start/stop

parent 2fdc5057
/*
* 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;
}
/*
* 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_;
};
......@@ -92,6 +92,11 @@ PulseLayer::connectPulseAudioServer( void )
//serverinfo();
//muteAudioApps(99);
_debug("Context creation done\n");
//FILE_TYPE ft = FILE_WAV;
//SOUND_FORMAT sf = INT16;
//audioRec.setSndSamplingRate(44100);
//audioRec.openFile("SFLWavFile.wav",ft,sf);
}
void PulseLayer::context_state_callback( pa_context* c, void* user_data )
......@@ -243,6 +248,13 @@ PulseLayer::startStream (void)
pa_threaded_mainloop_lock(m);
pa_stream_cork( record->pulseStream(), NULL, NULL, NULL);
pa_threaded_mainloop_unlock(m);
_debug("Opening the wave file\n");
FILE_TYPE ft = FILE_WAV;
SOUND_FORMAT sf = INT16;
audioRec.setSndSamplingRate(44100);
audioRec.openFile("SFLWavFile.wav",ft,sf);
}
void
......@@ -252,6 +264,9 @@ PulseLayer::stopStream (void)
pa_stream_flush( playback->pulseStream(), NULL, NULL );
pa_stream_flush( record->pulseStream(), NULL, NULL );
flushMic();
_debug("Closing the wav file\n");
audioRec.closeFile();
}
......
......@@ -256,6 +256,11 @@ class PulseLayer : public AudioLayer {
int spkrVolume;
int micVolume;
/**
* Audio device to record audio streams on disk
*/
AudioRecord audioRec;
public:
static int streamState;
};
......
......@@ -79,16 +79,16 @@ bool AudioRecord::setRawFile(const char *fileName) {
if ( strstr(name, ".raw") == NULL) strcat(name, ".raw");
fp = fopen(name, "wb");
if ( !fp ) {
cout << "AudioRecord: could not create RAW file: " << name << '.';
_debug("AudioRecord: could not create RAW file!\n");
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 << '.';
_debug("AudioRecord: using 16-bit signed integer data format for file.\n");
}
cout << "AudioRecord: creating RAW file: " << name;
_debug("AudioRecord: creating RAW file.\n");
return true;
}
......@@ -100,7 +100,7 @@ bool AudioRecord::setWavFile(const char *fileName) {
if ( strstr(name, ".wav") == NULL) strcat(name, ".wav");
fp = fopen(name, "wb");
if ( !fp ) {
cout << "AudioRecord: could not create WAV file: " << name;
_debug("AudioRecord: could not create WAV file.\n");
return false;
}
......@@ -117,13 +117,13 @@ bool AudioRecord::setWavFile(const char *fileName) {
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 << '.';
if ( fwrite(&hdr, 4, 11, fp) != 11) {
_debug("AudioRecord: could not write WAV header for file.\n");
return false;
}
cout << "AudioRecord: creating WAV file: " << name;
_debug("AudioRecord: creating WAV file.\n");
return true;
}
......@@ -149,20 +149,19 @@ void AudioRecord::closeWavFile()
void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) {
if (fp == 0){
cout << "AudioRecord: Can't record data, a file has not yet been opened!";
_debug("AudioRecord: Can't record data, a file has not yet been opened!\n");
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!";
_debug("AudioRecord: Could not record data!\n");
}
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!";
_debug("AudioRecord: Could not record data!\n");
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment