~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to gnuradio-core/src/lib/io/gr_wavfile_sink.cc

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c++ -*- */
 
2
/*
 
3
 * Copyright 2004,2006,2007,2008 Free Software Foundation, Inc.
 
4
 *
 
5
 * This file is part of GNU Radio
 
6
 *
 
7
 * GNU Radio is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 3, or (at your option)
 
10
 * any later version.
 
11
 *
 
12
 * GNU Radio is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with GNU Radio; see the file COPYING.  If not, write to
 
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
 
20
 * Boston, MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "config.h"
 
25
#endif
 
26
 
 
27
#include <gr_wavfile_sink.h>
 
28
#include <gr_io_signature.h>
 
29
#include <gri_wavfile.h>
 
30
#include <stdexcept>
 
31
#include <climits>
 
32
#include <cstring>
 
33
#include <cmath>
 
34
#include <fcntl.h>
 
35
 
 
36
// win32 (mingw/msvc) specific
 
37
#ifdef HAVE_IO_H
 
38
#include <io.h>
 
39
#endif
 
40
#ifdef O_BINARY
 
41
#define OUR_O_BINARY O_BINARY
 
42
#else
 
43
#define OUR_O_BINARY 0
 
44
#endif
 
45
 
 
46
// should be handled via configure
 
47
#ifdef O_LARGEFILE
 
48
#define OUR_O_LARGEFILE O_LARGEFILE
 
49
#else
 
50
#define OUR_O_LARGEFILE 0
 
51
#endif
 
52
 
 
53
 
 
54
gr_wavfile_sink_sptr
 
55
gr_make_wavfile_sink(const char *filename,
 
56
                     int n_channels,
 
57
                     unsigned int sample_rate,
 
58
                     int bits_per_sample)
 
59
{
 
60
  return gr_wavfile_sink_sptr (new gr_wavfile_sink (filename,
 
61
                                                    n_channels,
 
62
                                                    sample_rate,
 
63
                                                    bits_per_sample));
 
64
}
 
65
 
 
66
gr_wavfile_sink::gr_wavfile_sink(const char *filename,
 
67
                                 int n_channels,
 
68
                                 unsigned int sample_rate,
 
69
                                 int bits_per_sample)
 
70
  : gr_sync_block ("wavfile_sink",
 
71
                   gr_make_io_signature(1, n_channels, sizeof(float)),
 
72
                   gr_make_io_signature(0, 0, 0)),
 
73
    d_sample_rate(sample_rate), d_nchans(n_channels),
 
74
    d_fp(0), d_new_fp(0), d_updated(false)
 
75
{
 
76
  if (bits_per_sample != 8 && bits_per_sample != 16) {
 
77
    throw std::runtime_error("Invalid bits per sample (supports 8 and 16)");
 
78
  }
 
79
  d_bytes_per_sample = bits_per_sample / 8;
 
80
  d_bytes_per_sample_new = d_bytes_per_sample;
 
81
  
 
82
  if (!open(filename)) {
 
83
    throw std::runtime_error ("can't open file");
 
84
  }
 
85
 
 
86
  if (bits_per_sample == 8) {
 
87
    d_max_sample_val = 0xFF;
 
88
    d_min_sample_val = 0;
 
89
    d_normalize_fac  = d_max_sample_val/2;
 
90
    d_normalize_shift = 1;
 
91
  } else {
 
92
    d_max_sample_val = 0x7FFF;
 
93
    d_min_sample_val = -0x7FFF;
 
94
    d_normalize_fac  = d_max_sample_val;
 
95
    d_normalize_shift = 0;
 
96
    if (bits_per_sample != 16) {
 
97
      fprintf(stderr, "Invalid bits per sample value requested, using 16");
 
98
    }
 
99
  }
 
100
}
 
101
 
 
102
 
 
103
bool
 
104
gr_wavfile_sink::open(const char* filename)
 
105
{
 
106
  omni_mutex_lock l(d_mutex);
 
107
  
 
108
  // we use the open system call to get access to the O_LARGEFILE flag.
 
109
  int fd;
 
110
  if ((fd = ::open (filename,
 
111
                    O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY,
 
112
                    0664)) < 0){
 
113
    perror (filename);
 
114
    return false;
 
115
  }
 
116
 
 
117
  if (d_new_fp) {    // if we've already got a new one open, close it
 
118
    fclose(d_new_fp);
 
119
    d_new_fp = 0;
 
120
  }
 
121
  
 
122
  if ((d_new_fp = fdopen (fd, "wb")) == NULL) {
 
123
    perror (filename);
 
124
    ::close(fd);  // don't leak file descriptor if fdopen fails.
 
125
    return false;
 
126
  }
 
127
  d_updated = true;
 
128
  
 
129
  if (!gri_wavheader_write(d_new_fp,
 
130
                           d_sample_rate,
 
131
                           d_nchans,
 
132
                           d_bytes_per_sample_new)) {
 
133
    fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__);
 
134
    exit(-1);
 
135
  }
 
136
  
 
137
  return true;
 
138
}
 
139
 
 
140
 
 
141
void
 
142
gr_wavfile_sink::close()
 
143
{
 
144
  omni_mutex_lock l(d_mutex);
 
145
  
 
146
  if (!d_fp)
 
147
    return;
 
148
  
 
149
  close_wav();
 
150
}
 
151
 
 
152
void gr_wavfile_sink::close_wav()
 
153
{
 
154
  unsigned int byte_count = d_sample_count * d_bytes_per_sample;
 
155
  
 
156
  gri_wavheader_complete(d_fp, byte_count);
 
157
  
 
158
  fclose(d_fp);
 
159
  d_fp = NULL;
 
160
}
 
161
 
 
162
 
 
163
gr_wavfile_sink::~gr_wavfile_sink ()
 
164
{
 
165
  if (d_new_fp) {
 
166
    fclose(d_new_fp);
 
167
  }
 
168
 
 
169
  close();
 
170
}
 
171
 
 
172
 
 
173
int
 
174
gr_wavfile_sink::work (int noutput_items,
 
175
                       gr_vector_const_void_star &input_items,
 
176
                       gr_vector_void_star &output_items)
 
177
{
 
178
  float **in = (float **) &input_items[0];
 
179
  int n_in_chans = input_items.size();
 
180
  
 
181
  short int sample_buf_s;
 
182
  
 
183
  int nwritten;
 
184
  
 
185
  do_update();  // update: d_fp is reqd
 
186
  if (!d_fp)    // drop output on the floor
 
187
    return noutput_items;
 
188
  
 
189
  for (nwritten = 0; nwritten < noutput_items; nwritten++) {
 
190
    for (int chan = 0; chan < d_nchans; chan++) {
 
191
      // Write zeros to channels which are in the WAV file
 
192
      // but don't have any inputs here
 
193
      if (chan < n_in_chans) {
 
194
        sample_buf_s = 
 
195
          convert_to_short(in[chan][nwritten]);
 
196
      } else {
 
197
        sample_buf_s = 0;
 
198
      }
 
199
      
 
200
      gri_wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample);
 
201
      
 
202
      if (feof(d_fp) || ferror(d_fp)) {
 
203
        fprintf(stderr, "[%s] file i/o error\n", __FILE__);
 
204
        close();
 
205
        exit(-1);
 
206
      }
 
207
      d_sample_count++;
 
208
    }
 
209
  }
 
210
  
 
211
  return nwritten;
 
212
}
 
213
 
 
214
 
 
215
short int
 
216
gr_wavfile_sink::convert_to_short(float sample)
 
217
{
 
218
  sample += d_normalize_shift;
 
219
  sample *= d_normalize_fac;
 
220
  if (sample > d_max_sample_val) {
 
221
    sample = d_max_sample_val;
 
222
  } else if (sample < d_min_sample_val) {
 
223
    sample = d_min_sample_val;
 
224
  }
 
225
  
 
226
  return (short int) roundf(sample);
 
227
}
 
228
 
 
229
 
 
230
void
 
231
gr_wavfile_sink::set_bits_per_sample(int bits_per_sample)
 
232
{
 
233
  omni_mutex_lock l(d_mutex);
 
234
  if (bits_per_sample == 8 || bits_per_sample == 16) {
 
235
    d_bytes_per_sample_new = bits_per_sample / 8;
 
236
  }
 
237
}
 
238
 
 
239
 
 
240
void
 
241
gr_wavfile_sink::set_sample_rate(unsigned int sample_rate)
 
242
{
 
243
  omni_mutex_lock l(d_mutex);
 
244
  d_sample_rate = sample_rate;
 
245
}
 
246
 
 
247
 
 
248
void
 
249
gr_wavfile_sink::do_update()
 
250
{
 
251
  if (!d_updated) {
 
252
    return;
 
253
  }
 
254
  
 
255
  omni_mutex_lock     l(d_mutex);     // hold mutex for duration of this block
 
256
  if (d_fp) {
 
257
    close_wav();
 
258
  }
 
259
 
 
260
  d_fp = d_new_fp;                    // install new file pointer
 
261
  d_new_fp  = 0;
 
262
  d_sample_count = 0;
 
263
  d_bytes_per_sample = d_bytes_per_sample_new;
 
264
 
 
265
  if (d_bytes_per_sample == 1) {
 
266
    d_max_sample_val = UCHAR_MAX;
 
267
    d_min_sample_val = 0;
 
268
    d_normalize_fac  = d_max_sample_val/2;
 
269
    d_normalize_shift = 1;
 
270
  } else if (d_bytes_per_sample == 2) {
 
271
    d_max_sample_val = SHRT_MAX;
 
272
    d_min_sample_val = SHRT_MIN;
 
273
    d_normalize_fac  = d_max_sample_val;
 
274
    d_normalize_shift = 0;
 
275
  }
 
276
  
 
277
  d_updated = false;
 
278
}