audiorecord.cpp 11.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 *  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"

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 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
};
38
39


40
AudioRecord::AudioRecord(){
alexandresavard's avatar
alexandresavard committed
41
  
42
43
44
  sndSmplRate_ = 44100;
  channels_ = 1;
  byteCounter_ = 0;
alexandresavard's avatar
alexandresavard committed
45
  recordingEnabled_ = false;
46
  fp = 0;
47

alexandresavard's avatar
alexandresavard committed
48
49
  createFilename();
  
50
51
52
53
}


void AudioRecord::setSndSamplingRate(int smplRate){
alexandresavard's avatar
alexandresavard committed
54
  sndSmplRate_ = smplRate;  
55
56
}

57
void AudioRecord::setRecordingOption(FILE_TYPE type, SOUND_FORMAT format, int sndSmplRate, std::string path){
58
 
59
60
61
    std::string fName;

    fileType_ = type;
62
63
64
  sndFormat_ = format;
  channels_ = 1;
  sndSmplRate_ = sndSmplRate;
65
  
66
  if (fileType_ == FILE_RAW){
67
68
69
70
71
72
73
74
75
76
77
     if ( strstr(fileName_, ".raw") == NULL){
       printf("AudioRecord::openFile::concatenate .raw file extension: name : %s \n", fileName_); 
       strcat(fileName_, ".raw");
     }
   }
   else if (fileType_ == FILE_WAV){
     if ( strstr(fileName_, ".wav") == NULL){ 
       printf("AudioRecord::openFile::concatenate .wav file extension: name : %s \n", fileName_);
       strcat(fileName_, ".wav");
     }
   }
78
79
80
81
82

   fName = fileName_;
   savePath_ = path + "/";
   savePath_.append(fName);

83
84
85
86
}

void AudioRecord::openFile(){
  
alexandresavard's avatar
alexandresavard committed
87
   
88
89
90
   _debug("AudioRecord::openFile()\n");  
  
   bool result = false;
91
   
alexandresavard's avatar
alexandresavard committed
92
   _debug("AudioRecord::openFile()\n");
93
   if(isFileExist()) {
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
     _debug("AudioRecord::Filename does not exist, creating one \n");
     byteCounter_ = 0;

     if(fileType_ == FILE_RAW){
       result = setRawFile();
     }
     else if (fileType_ == FILE_WAV){
       result = setWavFile();
     }
   }
   else {
     _debug("AudioRecord::Filename already exist opening it \n");
     if(fileType_ == FILE_RAW){
       result = openExistingRawFile();
     }   
     else if (fileType_ == FILE_WAV){
       result = openExistingWavFile();      
     }
   }  
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
}


void AudioRecord::closeFile() {

  if (fp == 0) return;

  if (fileType_ == FILE_RAW)
    fclose(fp);
  else if (fileType_ == FILE_WAV)
    this->closeWavFile();

}


bool AudioRecord::isOpenFile() {
  
130
131
  if(fp){
    _debug("AudioRecord::isOpenFile(): file already openend\n");
132
    return true;
133
134
135
  }
  else {
    _debug("AudioRecord::isOpenFIle(): file not openend \n");
136
    return false;
137
  }
138
139
140
}


141
142
143
144
145
146
147
148
149
150
bool AudioRecord::isFileExist() {
  
  printf("AudioRecord::isFileExist(): try to open name : %s \n", fileName_);
  if(fopen(fileName_,"rb")==0) {
    return true;
  }
  
  return false;  
}

151
152
153
154
155
156
157
158
159
bool AudioRecord::isRecording() {
  _debug("AudioRecording::setRecording() \n");
  
  if(recordingEnabled_)
    return true;
  else 
    return false;
}

160

alexandresavard's avatar
alexandresavard committed
161
bool AudioRecord::setRecording() {
162
  _debug("AudioRecord::setRecording()\n");
alexandresavard's avatar
alexandresavard committed
163
  
164
165
166
167
168
169
170
171
172
173
174
175
176
  if (isOpenFile()){
    _debug("AuioRecord::setRecording()::file already opened\n");
    if(!recordingEnabled_)
      recordingEnabled_ = true;
    else 
      recordingEnabled_ = false;
  }
  else {
    _debug("AudioRecord::setRecording():Opening the wave file in call during call instantiation\n");
    openFile();

    recordingEnabled_ = true; // once opend file, start recording
  }
alexandresavard's avatar
alexandresavard committed
177
178
179
  
}

180
181
182
183
184
185
186
void AudioRecord::stopRecording() {
  _debug("AudioRecording::stopRecording() \n");

  if(recordingEnabled_)
    recordingEnabled_ = false;
}

alexandresavard's avatar
alexandresavard committed
187

alexandresavard's avatar
alexandresavard committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
void AudioRecord::createFilename(){
    
    time_t rawtime;
    struct tm * timeinfo;

    rawtime = time(NULL);
    timeinfo = localtime ( &rawtime );

    stringstream out;
    
    // DATE
    out << timeinfo->tm_year+1900;
    if (timeinfo->tm_mon < 9) // january is 01, not 1
      out << 0;
    out << timeinfo->tm_mon+1;
    if (timeinfo->tm_mday < 10) // 01 02 03, not 1 2 3
      out << 0;
    out << timeinfo->tm_mday;
 
    out << '-';
   
    // hour
    if (timeinfo->tm_hour < 10) // 01 02 03, not 1 2 3
      out << 0;
    out << timeinfo->tm_hour;
alexandresavard's avatar
alexandresavard committed
213
    out << ':';
alexandresavard's avatar
alexandresavard committed
214
215
216
    if (timeinfo->tm_min < 10) // 01 02 03, not 1 2 3
      out << 0;
    out << timeinfo->tm_min;
alexandresavard's avatar
alexandresavard committed
217
    out << ':';
alexandresavard's avatar
alexandresavard committed
218
219
220
221
222
223
224
225
226
227
    if (timeinfo->tm_sec < 10) // 01 02 03,  not 1 2 3
      out << 0;
    out << timeinfo->tm_sec;

    // fileName_ = out.str();
    strncpy(fileName_, out.str().c_str(), 8192);

    printf("AudioRecord::createFilename::filename for this call %s \n",fileName_);
}

228
bool AudioRecord::setRawFile() {
229

alexandresavard's avatar
alexandresavard committed
230
  fp = fopen(savePath_.c_str(), "wb");
231
  if ( !fp ) {
232
    _debug("AudioRecord::setRawFile() : could not create RAW file!\n");
233
234
235
236
237
    return false;
  }

  if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16
    sndFormat_ = INT16;
238
    _debug("AudioRecord::setRawFile() : using 16-bit signed integer data format for file.\n");
239
240
  }

241
  _debug("AudioRecord:setRawFile() : created RAW file.\n");
242
243
244
245
  return true;
}


246
bool AudioRecord::setWavFile() {
247
  
alexandresavard's avatar
alexandresavard committed
248
  fp = fopen(savePath_.c_str(), "wb");
249
  if ( !fp ) {
250
    _debug("AudioRecord::setWavFile() : could not create WAV file.\n");
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
    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);

267
268
  
  if ( fwrite(&hdr, 4, 11, fp) != 11) {
269
    _debug("AudioRecord::setWavFile() : could not write WAV header for file. \n");
270
271
272
    return false;
  }

273
  _debug("AudioRecord::setWavFile() : created WAV file. \n");
274
275
276
277
  return true;
}


278
279
280
281
282
283
284
285
bool AudioRecord::openExistingRawFile()
{ 
  fp = fopen(fileName_, "ab+");
  if ( !fp ) {
    _debug("AudioRecord::openExistingRawFile() : could not create RAW file!\n");
    return false;
  }
}
286
287


288
289
290
bool AudioRecord::openExistingWavFile()
{ 
  _debug("AudioRecord::openExistingWavFile() \n");
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  fp = fopen(fileName_, "rb+");
  if ( !fp ) {
    _debug("AudioRecord::openExistingWavFile() : could not open WAV file rb+!\n");
    return false;
  }

  printf("AudioRecord::openExistingWavFile()::Tried to open %s \n",fileName_);
  
  if(fseek(fp, 40, SEEK_SET) != 0) // jump to data length
    _debug("AudioRecord::OpenExistingWavFile: 1.Couldn't seek offset 40 in the file \n");
  
  if(fread(&byteCounter_, 4, 1, fp))
    _debug("AudioRecord::OpenExistingWavFile : bytecounter Read successfully \n");
  
  if(fseek (fp, 0 , SEEK_END) != 0)
    _debug("AudioRecors::OpenExistingWavFile : 2.Couldn't seek at the en of the file \n");
308

309
  printf("AudioRecord::OpenExistingWavFile : Byte counter after oppening : %d \n",(int)byteCounter_);
310

311
312
  if ( fclose( fp ) != 0)
    _debug("AudioRecord::openExistingWavFile()::ERROR: can't close file r+ \n");
313

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

  
  fp = fopen(fileName_, "ab+");
  if ( !fp ) {
    _debug("AudioRecord::openExistingWavFile() : could not createopen WAV file ab+!\n");
    return false;
  }

  if(fseek (fp, 4 , SEEK_END) != 0)
    _debug("AudioRecors::OpenExistingWavFile : 2.Couldn't seek at the en of the file \n");
  
}


void AudioRecord::closeWavFile() 
{
330
  if (fp == 0){
331
    _debug("AudioRecord:: Can't closeWavFile, a file has not yet been opened!\n");
332
333
334
    return;
  }
 
335
336
337
338
339
340
341
342
343
344
345
  _debug("AudioRecord::closeWavFile() \n");

  if ( fclose( fp ) != 0)
    _debug("AudioRecord::closeWavFile()::ERROR: can't close file ab \n");

  

  fp = fopen(fileName_, "rb+");
  if ( !fp ) {
    _debug("AudioRecord::closeWavFile() : could not open WAV file rb+!\n");
    return;
346
347
  }

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

  SINT32 bytes = byteCounter_ * channels_;
  fseek(fp, 40, SEEK_SET); // jump to data length
  if (ferror(fp))perror("AudioRecord::closeWavFile()::ERROR: can't reach offset 40\n");
  
  fwrite(&bytes, sizeof(SINT32), 1, fp);
  if (ferror(fp))perror("AudioRecord::closeWavFile()::ERROR: can't write bytes for data length \n");
  printf("AudioRecord::closeWavFile : data bytes: %i \n",(int)bytes);

  bytes = byteCounter_ * channels_ + 44; // + 44 for the wave header 
  fseek(fp, 4, SEEK_SET);  // jump to file size
  if (ferror(fp))perror("AudioRecord::closeWavFile()::ERROR: can't reach offset 4\n");
  
  fwrite(&bytes, 4, 1, fp);
  if (ferror(fp))perror("AudioRecord::closeWavFile()::ERROR: can't reach offset 4\n");
363
  
364
365
366
367
368
369
370
371
372
373
  printf("AudioRecord::closeWavFile : bytes : %i \n",(int)bytes);
  
  if ( fclose( fp ) != 0)
    _debug("AudioRecord::closeWavFile()::ERROR: can't close file\n");
 
  // i = fclose(fp);
  // printf("AudioRecord::closeWavFile : indicator i : %i \n",i);

}

374

375
void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) {
376

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  if (recordingEnabled_) {

    if (fp == 0){
      _debug("AudioRecord: Can't record data, a file has not yet been opened!\n");
      return;
    }
 
    // int size = nSamples * (sizeof(SFLDataFormat));
    // int size = sizeof(buffer);
    // int count = sizeof(buffer) / sizeof(SFLDataFormat);
  
    // printf("AudioRecord : sizeof(buffer) : %d \n",size); 
    // printf("AudioRecord : sizeof(buffer) / sizeof(SFLDataFormat) : %d \n",count);
    // printf("AudioRecord : nSamples : %d \n",nSamples);
    // printf("AudioRecord : buffer: %x : ", buffer);
 
    if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16
      if ( fwrite(buffer, sizeof(SFLDataFormat), nSamples, fp) != nSamples)
        _debug("AudioRecord: Could not record data! \n");
      else {
        // printf("Buffer : %x \n",*buffer);
        fflush(fp);
        // _debug("Flushing!\n");
        byteCounter_ += (unsigned long)(nSamples*sizeof(SFLDataFormat));
      }
    } 
  }
404
405
406
407

  return;
}

408
409
410

void AudioRecord::recData(SFLDataFormat* buffer_1, SFLDataFormat* buffer_2, int nSamples_1, int nSamples_2) {

411
  if (recordingEnabled_) {
412

413
414
415
416
417
418
    if (fp == 0){
      _debug("AudioRecord: Can't record data, a file has not yet been opened!\n");
      return;
    }

    mixBuffer_ = new SFLDataFormat[nSamples_1]; 
419
 
420
421
422
423
424
425
426
427
    // int size = nSamples * (sizeof(SFLDataFormat));
    // int size = sizeof(buffer);
    // int count = sizeof(buffer) / sizeof(SFLDataFormat);
  
    // printf("AudioRecord : sizeof(buffer) : %d \n",size); 
    // printf("AudioRecord : sizeof(buffer) / sizeof(SFLDataFormat) : %d \n",count);
    // printf("AudioRecord : nSamples : %d \n",nSamples);
    // printf("AudioRecord : buffer: %x : ", buffer);
alexandresavard's avatar
alexandresavard committed
428
429
430

    if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16
      for (int k=0; k<nSamples_1; k++){
431
      
alexandresavard's avatar
alexandresavard committed
432
        mixBuffer_[k] = (buffer_1[k]+buffer_2[k])/2;
433
      
alexandresavard's avatar
alexandresavard committed
434
435
436
437
438
439
440
        if ( fwrite(&buffer_1[k], 2, 1, fp) != 1)
          _debug("AudioRecord: Could not record data!\n");
        else {
          // printf("Buffer : %x \n",*buffer);
          fflush(fp);
          // _debug("Flushing!\n");
        }
441
442
      }
    }
443
   
444
    byteCounter_ += (unsigned long)(nSamples_1*sizeof(SFLDataFormat));
445

Emmanuel Milou's avatar
Emmanuel Milou committed
446
    //printf("AudioRecord::recData():: byteCounter_ : %i \n",(int)byteCounter_ );
447

448
449
    delete [] mixBuffer_;
  }
450
451
452

  return;
}