YARP  2.3.70.2
Yet Another Robot Platform
SoundFile.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 RobotCub Consortium
3  * Authors: Paul Fitzpatrick
4  * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
5  */
6 
7 #include <yarp/sig/SoundFile.h>
8 
9 #include <yarp/conf/system.h>
10 
11 #include <yarp/os/NetInt16.h>
12 #include <yarp/os/NetInt32.h>
13 #include <yarp/os/ManagedBytes.h>
14 #include <yarp/os/Vocab.h>
15 
16 #include <yarp/sig/Sound.h>
17 
18 #include <cstdio>
19 #include <cstring>
20 
21 using namespace yarp::os;
22 using namespace yarp::sig;
23 using namespace yarp::sig::file;
24 
25 YARP_BEGIN_PACK
26 class PcmWavHeader {
27 public:
28  NetInt32 wavHeader;
29  NetInt32 wavLength;
30  NetInt32 formatHeader1;
31  NetInt32 formatHeader2;
32  NetInt32 formatLength;
33 
34  struct {
35  NetInt16 pcmFormatTag;
36  NetInt16 pcmChannels;
39  NetInt16 pcmBlockAlign;
40  NetInt16 pcmBitsPerSample;
41  } pcm;
43 
44  NetInt32 dummyHeader;
45  NetInt32 dummyLength;
47 
48  NetInt32 dataHeader;
49  NetInt32 dataLength;
50 
51  void setup_to_write(const Sound& sound, FILE *fp);
52  bool parse_from_file(FILE *fp);
53 };
54 YARP_END_PACK
55 
57 {
58  fread(&wavHeader,sizeof(wavHeader),1,fp);
59  fread(&wavLength,sizeof(wavLength),1,fp);
60  fread(&formatHeader1,sizeof(formatHeader1),1,fp);
61 
62  fread(&formatHeader2,sizeof(formatHeader2),1,fp);
63  fread(&formatLength,sizeof(formatLength),1,fp);
64 
65  fread(&pcm.pcmFormatTag,sizeof(pcm.pcmFormatTag),1,fp);
66  fread(&pcm.pcmChannels,sizeof(pcm.pcmChannels),1,fp);
67  fread(&pcm.pcmSamplesPerSecond,sizeof(pcm.pcmSamplesPerSecond),1,fp);
68  fread(&pcm.pcmBytesPerSecond,sizeof(pcm.pcmBytesPerSecond),1,fp);
69  fread(&pcm.pcmBlockAlign,sizeof(pcm.pcmBlockAlign),1,fp);
70  fread(&pcm.pcmBitsPerSample,sizeof(pcm.pcmBitsPerSample),1,fp);
71  if (pcm.pcmBitsPerSample!=16)
72  {
73  printf("sorry, lousy wav read code only does 16-bit ints\n");
74  return false;
75  }
76 
77  //extra bytes in pcm chuck
78  int extra_size = formatLength-sizeof(pcm);
79  pcmExtraData.allocate(extra_size);
80  fread(&pcmExtraData,extra_size,1,fp);
81 
82  //extra chuncks
83  fread(&dummyHeader,sizeof(dummyHeader),1,fp);
84 
85  while (dummyHeader!=VOCAB4('d','a','t','a'))
86  {
87  fread(&dummyLength,sizeof(dummyLength),1,fp);
88  dummyData.clear();
89  dummyData.allocate(dummyLength);
90  fread(&dummyData,dummyLength,1,fp);
91  fread(&dummyHeader,sizeof(dummyHeader),1,fp);
92  }
93 
94  dataHeader=dummyHeader;
95  fread(&dataLength,sizeof(dataLength),1,fp);
96 
97  return true;
98 }
99 
100 void PcmWavHeader::setup_to_write(const Sound& src, FILE *fp)
101 {
102  int bitsPerSample = 16;
103  int channels = src.getChannels();
104  int bytes = channels*src.getSamples()*2;
105  int align = channels*((bitsPerSample+7)/8);
106 
107  wavHeader = VOCAB4('R','I','F','F');
108  wavLength = bytes + sizeof(PcmWavHeader) - 2*sizeof(NetInt32);
109  formatHeader1 = VOCAB4('W','A','V','E');
110  formatHeader2 = VOCAB4('f','m','t',' ');
111  formatLength = sizeof(pcm);
112 
113  pcm.pcmFormatTag = 1; /* PCM! */
114  pcm.pcmChannels = channels;
115  pcm.pcmSamplesPerSecond = (int)src.getFrequency();
116  pcm.pcmBytesPerSecond = align*pcm.pcmSamplesPerSecond;
117  pcm.pcmBlockAlign = align;
118  pcm.pcmBitsPerSample = bitsPerSample;
119 
120  dataHeader = VOCAB4('d','a','t','a');
121  dataLength = bytes;
122 
123 
124  fwrite(&wavHeader,sizeof(wavHeader),1,fp);
125  fwrite(&wavLength,sizeof(wavLength),1,fp);
126  fwrite(&formatHeader1,sizeof(formatHeader1),1,fp);
127 
128  fwrite(&formatHeader2,sizeof(formatHeader2),1,fp);
129  fwrite(&formatLength,sizeof(formatLength),1,fp);
130 
131  fwrite(&pcm.pcmFormatTag,sizeof(pcm.pcmFormatTag),1,fp);
132  fwrite(&pcm.pcmChannels,sizeof(pcm.pcmChannels),1,fp);
133  fwrite(&pcm.pcmSamplesPerSecond,sizeof(pcm.pcmSamplesPerSecond),1,fp);
134  fwrite(&pcm.pcmBytesPerSecond,sizeof(pcm.pcmBytesPerSecond),1,fp);
135  fwrite(&pcm.pcmBlockAlign,sizeof(pcm.pcmBlockAlign),1,fp);
136  fwrite(&pcm.pcmBitsPerSample,sizeof(pcm.pcmBitsPerSample),1,fp);
137 
138  fwrite(&dataHeader,sizeof(dataHeader),1,fp);
139  fwrite(&dataLength,sizeof(dataLength),1,fp);
140 
141 }
142 
143 bool yarp::sig::file::read(Sound& dest, const char *src)
144 {
145  FILE *fp = fopen(src, "rb");
146  if (!fp) {
147  printf("cannot open file %s for reading\n", src);
148  return false;
149  }
150 
152  if (!header.parse_from_file(fp))
153  {
154  printf("error parsing header of file %s\n", src);
155  fclose(fp);
156  return false;
157  };
158 
159 
160  int freq = header.pcm.pcmSamplesPerSecond;
161  int channels = header.pcm.pcmChannels;
162  int bits = header.pcm.pcmBitsPerSample;
163  int samples = header.dataLength/(bits/8)/channels;
164  dest.resize(samples,channels);
165  dest.setFrequency(freq);
166  ManagedBytes bytes(header.dataLength);
167  printf("%d channels %d samples %d frequency\n", channels, samples, freq);
168 
169  size_t result;
170  result = fread(bytes.get(),bytes.length(),1,fp);
171  YARP_UNUSED(result);
172 
173  NetInt16 *data = (NetInt16*)bytes.get();
174  int ct = 0;
175  for (int i=0; i<samples; i++) {
176  for (int j=0; j<channels; j++) {
177  dest.set(data[ct],i,j);
178  ct++;
179  }
180  }
181 
182  fclose(fp);
183  return true;
184 }
185 
186 
187 bool yarp::sig::file::write(const Sound& src, const char *dest)
188 {
189  FILE *fp = fopen(dest, "wb");
190  if (!fp) {
191  printf("cannot open file %s for writing\n", dest);
192  return false;
193  }
194 
196  header.setup_to_write(src, fp);
197 
198  ManagedBytes bytes(header.dataLength);
199  NetInt16 *data = (NetInt16*)bytes.get();
200  int ct = 0;
201  int samples = src.getSamples();
202  int channels = src.getChannels();
203  for (int i=0; i<samples; i++) {
204  for (int j=0; j<channels; j++) {
205  int v = src.get(i,j);
206  data[ct] = v;
207  ct++;
208  }
209  }
210  fwrite(bytes.get(),bytes.length(),1,fp);
211 
212  fclose(fp);
213  return true;
214 }
215 
217 {
218  if (fp)
219  {
220  printf("file %s is already open\n", fname);
221  return false;
222  }
223 
224  fp = fopen(filename, "rb");
225  if (!fp)
226  {
227  printf("cannot open file %s for reading\n", filename);
228  return false;
229  }
230  strcpy(fname,filename);
232  if (!header.parse_from_file(fp))
233  {
234  printf("error parsing header of file %s\n", fname);
235  fclose(fp);
236  return false;
237  }
238  this->soundInfo.freq = header.pcm.pcmSamplesPerSecond;
239  this->soundInfo.channels = header.pcm.pcmChannels;
240  this->soundInfo.bits = header.pcm.pcmBitsPerSample;
241  this->soundInfo.samples = header.dataLength/(this->soundInfo.bits/8)/this->soundInfo.channels;
242  this->soundInfo.data_start_offset = ftell(fp);
243 
244  return true;
245 }
246 
248 {
249  if (!fp)
250  {
251  printf("no files open\n");
252  return false;
253  }
254 
255  fclose(fp);
256  fname[0]=0;
257  index=0;
258  return true;
259 }
260 
262 {
263  int expected_bytes = block_size*(soundInfo.bits/8)*soundInfo.channels;
264 
265  //this probably works only if soundInfo.bits=16
266  int expected_words=expected_bytes/(soundInfo.bits/8);
267  NetInt16 *data = new NetInt16 [expected_words];
268 
269  int bytes_read = fread(data,1,expected_bytes,fp);
270  int samples_read = bytes_read/(soundInfo.bits/8)/soundInfo.channels;
271 
272  dest.resize(samples_read,soundInfo.channels);
273  dest.setFrequency(soundInfo.freq);
274 
275  int ct = 0;
276  for (int i=0; i<samples_read; i++) {
277  for (int j=0; j<soundInfo.channels; j++) {
278  dest.set(data[ct],i,j);
279  ct++;
280  }
281  }
282  index+=samples_read;
283 
284  delete [] data;
285  return samples_read;
286 }
287 
289 {
290  if (!fp)
291  {
292  printf("no files open\n");
293  return false;
294  }
295 
296  if ((int)sample_offset>this->soundInfo.samples)
297  {
298  printf("invalid sample_offset\n");
299  return false;
300  }
301 
302  fseek(fp,this->soundInfo.data_start_offset+(sample_offset*this->soundInfo.channels*this->soundInfo.bits/2),SEEK_SET);
303  index=sample_offset;
304 
305  return true;
306 }
307 
309 {
310  return index;
311 }
int getFrequency() const
Definition: Sound.cpp:183
NetInt32 formatLength
Definition: SoundFile.cpp:32
struct PcmWavHeader::@6 pcm
bool write(const ImageOf< PixelRgb > &src, const yarp::os::ConstString &dest)
Definition: ImageFile.cpp:412
bool parse_from_file(FILE *fp)
Definition: SoundFile.cpp:56
BlobNetworkHeader header
Definition: TcpRosStream.h:38
ManagedBytes dummyData
Definition: SoundFile.cpp:46
NetInt32 formatHeader2
Definition: SoundFile.cpp:31
void setup_to_write(const Sound &sound, FILE *fp)
Definition: SoundFile.cpp:100
bool rewind(size_t sample_offset=0)
Definition: SoundFile.cpp:288
NetInt16 pcmFormatTag
Definition: SoundFile.cpp:35
* dest
Definition: ImageCopy.cpp:72
NetInt32 pcmSamplesPerSecond
Definition: SoundFile.cpp:37
Class for storing sounds.
Definition: Sound.h:25
NetInt32 wavLength
Definition: SoundFile.cpp:29
bool open(const char *filename)
Definition: SoundFile.cpp:216
void setFrequency(int freq)
Definition: Sound.cpp:187
ManagedBytes pcmExtraData
Definition: SoundFile.cpp:42
NetInt32 dummyHeader
Definition: SoundFile.cpp:44
int getSamples() const
Definition: Sound.h:98
bool read(ImageOf< PixelRgb > &dest, const yarp::os::ConstString &src)
Definition: ImageFile.cpp:389
size_t readBlock(Sound &dest, size_t block_size)
Definition: SoundFile.cpp:261
NetInt32 pcmBytesPerSecond
Definition: SoundFile.cpp:38
NetInt16 pcmChannels
Definition: SoundFile.cpp:36
void resize(int samples, int channels=1)
Definition: Sound.cpp:150
int getChannels() const
Definition: Sound.h:100
NetInt16 pcmBlockAlign
Definition: SoundFile.cpp:39
void set(int value, int sample, int channel=0)
Definition: Sound.cpp:173
NetInt32 dummyLength
Definition: SoundFile.cpp:45
NetInt32 wavHeader
Definition: SoundFile.cpp:28
An interface to the operating system, including Port based communication.
NetInt32 dataLength
Definition: SoundFile.cpp:49
An abstraction for a block of bytes, with optional responsibility for allocating/destroying that bloc...
Definition: ManagedBytes.h:24
dest v
Definition: ImageCopy.cpp:62
int16_t * samples
Signal processing.
Definition: Image.h:20
int get(int sample, int channel=0) const
Definition: Sound.cpp:156
#define VOCAB4(a, b, c, d)
Definition: Vocab.h:23
NetInt32 dataHeader
Definition: SoundFile.cpp:48
NetInt16 pcmBitsPerSample
Definition: SoundFile.cpp:40
NetInt32 formatHeader1
Definition: SoundFile.cpp:30
Image file operations.
Definition: ImageFile.h:21