YARP  2.3.68+228-20170410.2+git7d0b2e0
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 <stdio.h>
19 #include <string.h>
20 
21 using namespace yarp::os;
22 using namespace yarp::sig;
23 using namespace yarp::sig::file;
24 
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 };
55 
57 {
58  size_t result;
59  result = fread(&wavHeader,sizeof(wavHeader),1,fp);
60  result = fread(&wavLength,sizeof(wavLength),1,fp);
61  result = fread(&formatHeader1,sizeof(formatHeader1),1,fp);
62 
63  result = fread(&formatHeader2,sizeof(formatHeader2),1,fp);
64  result = fread(&formatLength,sizeof(formatLength),1,fp);
65 
66  result = fread(&pcm.pcmFormatTag,sizeof(pcm.pcmFormatTag),1,fp);
67  result = fread(&pcm.pcmChannels,sizeof(pcm.pcmChannels),1,fp);
68  result = fread(&pcm.pcmSamplesPerSecond,sizeof(pcm.pcmSamplesPerSecond),1,fp);
69  result = fread(&pcm.pcmBytesPerSecond,sizeof(pcm.pcmBytesPerSecond),1,fp);
70  result = fread(&pcm.pcmBlockAlign,sizeof(pcm.pcmBlockAlign),1,fp);
71  result = fread(&pcm.pcmBitsPerSample,sizeof(pcm.pcmBitsPerSample),1,fp);
72  if (pcm.pcmBitsPerSample!=16)
73  {
74  printf("sorry, lousy wav read code only does 16-bit ints\n");
75  return false;
76  }
77 
78  //extra bytes in pcm chuck
79  int extra_size = formatLength-sizeof(pcm);
80  pcmExtraData.allocate(extra_size);
81  result = fread(&pcmExtraData,extra_size,1,fp);
82 
83  //extra chuncks
84  result = fread(&dummyHeader,sizeof(dummyHeader),1,fp);
85 
86  while (dummyHeader!=VOCAB4('d','a','t','a'))
87  {
88  result = fread(&dummyLength,sizeof(dummyLength),1,fp);
89  dummyData.clear();
90  dummyData.allocate(dummyLength);
91  result = fread(&dummyData,dummyLength,1,fp);
92  result = fread(&dummyHeader,sizeof(dummyHeader),1,fp);
93  }
94 
95  dataHeader=dummyHeader;
96  result = fread(&dataLength,sizeof(dataLength),1,fp);
97 
98  YARP_UNUSED(result);
99  return true;
100 }
101 
102 void PcmWavHeader::setup_to_write(const Sound& src, FILE *fp)
103 {
104  int bitsPerSample = 16;
105  int channels = src.getChannels();
106  int bytes = channels*src.getSamples()*2;
107  int align = channels*((bitsPerSample+7)/8);
108 
109  wavHeader = VOCAB4('R','I','F','F');
110  wavLength = bytes + sizeof(PcmWavHeader) - 2*sizeof(NetInt32);
111  formatHeader1 = VOCAB4('W','A','V','E');
112  formatHeader2 = VOCAB4('f','m','t',' ');
113  formatLength = sizeof(pcm);
114 
115  pcm.pcmFormatTag = 1; /* PCM! */
116  pcm.pcmChannels = channels;
117  pcm.pcmSamplesPerSecond = (int)src.getFrequency();
118  pcm.pcmBytesPerSecond = align*pcm.pcmSamplesPerSecond;
119  pcm.pcmBlockAlign = align;
120  pcm.pcmBitsPerSample = bitsPerSample;
121 
122  dataHeader = VOCAB4('d','a','t','a');
123  dataLength = bytes;
124 
125  size_t result;
126  result = fwrite(&wavHeader,sizeof(wavHeader),1,fp);
127  result = fwrite(&wavLength,sizeof(wavLength),1,fp);
128  result = fwrite(&formatHeader1,sizeof(formatHeader1),1,fp);
129 
130  result = fwrite(&formatHeader2,sizeof(formatHeader2),1,fp);
131  result = fwrite(&formatLength,sizeof(formatLength),1,fp);
132 
133  result = fwrite(&pcm.pcmFormatTag,sizeof(pcm.pcmFormatTag),1,fp);
134  result = fwrite(&pcm.pcmChannels,sizeof(pcm.pcmChannels),1,fp);
135  result = fwrite(&pcm.pcmSamplesPerSecond,sizeof(pcm.pcmSamplesPerSecond),1,fp);
136  result = fwrite(&pcm.pcmBytesPerSecond,sizeof(pcm.pcmBytesPerSecond),1,fp);
137  result = fwrite(&pcm.pcmBlockAlign,sizeof(pcm.pcmBlockAlign),1,fp);
138  result = fwrite(&pcm.pcmBitsPerSample,sizeof(pcm.pcmBitsPerSample),1,fp);
139 
140  result = fwrite(&dataHeader,sizeof(dataHeader),1,fp);
141  result = fwrite(&dataLength,sizeof(dataLength),1,fp);
142 
143  YARP_UNUSED(result);
144 }
145 
146 bool yarp::sig::file::read(Sound& dest, const char *src)
147 {
148  FILE *fp = fopen(src, "rb");
149  if (!fp) {
150  printf("cannot open file %s for reading\n", src);
151  return false;
152  }
153 
155  if (!header.parse_from_file(fp))
156  {
157  printf("error parsing header of file %s\n", src);
158  fclose(fp);
159  return false;
160  };
161 
162 
163  int freq = header.pcm.pcmSamplesPerSecond;
164  int channels = header.pcm.pcmChannels;
165  int bits = header.pcm.pcmBitsPerSample;
166  int samples = header.dataLength/(bits/8)/channels;
167  dest.resize(samples,channels);
168  dest.setFrequency(freq);
169  ManagedBytes bytes(header.dataLength);
170  printf("%d channels %d samples %d frequency\n", channels, samples, freq);
171 
172  size_t result;
173  result = fread(bytes.get(),bytes.length(),1,fp);
174  YARP_UNUSED(result);
175 
176  NetInt16 *data = (NetInt16*)bytes.get();
177  int ct = 0;
178  for (int i=0; i<samples; i++) {
179  for (int j=0; j<channels; j++) {
180  dest.set(data[ct],i,j);
181  ct++;
182  }
183  }
184 
185  fclose(fp);
186  return true;
187 }
188 
189 
190 bool yarp::sig::file::write(const Sound& src, const char *dest)
191 {
192  FILE *fp = fopen(dest, "wb");
193  if (!fp) {
194  printf("cannot open file %s for writing\n", dest);
195  return false;
196  }
197 
199  header.setup_to_write(src, fp);
200 
201  ManagedBytes bytes(header.dataLength);
202  NetInt16 *data = (NetInt16*)bytes.get();
203  int ct = 0;
204  int samples = src.getSamples();
205  int channels = src.getChannels();
206  for (int i=0; i<samples; i++) {
207  for (int j=0; j<channels; j++) {
208  int v = src.get(i,j);
209  data[ct] = v;
210  ct++;
211  }
212  }
213  fwrite(bytes.get(),bytes.length(),1,fp);
214 
215  fclose(fp);
216  return true;
217 }
218 
220 {
221  if (fp)
222  {
223  printf("file %s is already open\n", fname);
224  return false;
225  }
226 
227  fp = fopen(filename, "rb");
228  if (!fp)
229  {
230  printf("cannot open file %s for reading\n", filename);
231  return false;
232  }
233  strcpy(fname,filename);
235  if (!header.parse_from_file(fp))
236  {
237  printf("error parsing header of file %s\n", fname);
238  fclose(fp);
239  return false;
240  }
241  this->soundInfo.freq = header.pcm.pcmSamplesPerSecond;
242  this->soundInfo.channels = header.pcm.pcmChannels;
243  this->soundInfo.bits = header.pcm.pcmBitsPerSample;
244  this->soundInfo.samples = header.dataLength/(this->soundInfo.bits/8)/this->soundInfo.channels;
245  this->soundInfo.data_start_offset = ftell(fp);
246 
247  return true;
248 }
249 
251 {
252  if (!fp)
253  {
254  printf("no files open\n");
255  return false;
256  }
257 
258  fclose(fp);
259  fname[0]=0;
260  index=0;
261  return true;
262 }
263 
265 {
266  int expected_bytes = block_size*(soundInfo.bits/8)*soundInfo.channels;
267 
268  //this probably works only if soundInfo.bits=16
269  int expected_words=expected_bytes/(soundInfo.bits/8);
270  NetInt16 *data = new NetInt16 [expected_words];
271 
272  int bytes_read = fread(data,1,expected_bytes,fp);
273  int samples_read = bytes_read/(soundInfo.bits/8)/soundInfo.channels;
274 
275  dest.resize(samples_read,soundInfo.channels);
276  dest.setFrequency(soundInfo.freq);
277 
278  int ct = 0;
279  for (int i=0; i<samples_read; i++) {
280  for (int j=0; j<soundInfo.channels; j++) {
281  dest.set(data[ct],i,j);
282  ct++;
283  }
284  }
285  index+=samples_read;
286 
287  delete [] data;
288  return samples_read;
289 }
290 
292 {
293  if (!fp)
294  {
295  printf("no files open\n");
296  return false;
297  }
298 
299  if ((int)sample_offset>this->soundInfo.samples)
300  {
301  printf("invalid sample_offset\n");
302  return false;
303  }
304 
305  fseek(fp,this->soundInfo.data_start_offset+(sample_offset*this->soundInfo.channels*this->soundInfo.bits/2),SEEK_SET);
306  index=sample_offset;
307 
308  return true;
309 }
310 
312 {
313  return index;
314 }
int getFrequency() const
Definition: Sound.cpp:183
NetInt32 formatLength
Definition: SoundFile.cpp:32
#define YARP_END_PACK
Ends 1 byte packing for structs/classes.
Definition: system.h:206
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:102
bool rewind(size_t sample_offset=0)
Definition: SoundFile.cpp:291
NetInt16 pcmFormatTag
Definition: SoundFile.cpp:35
#define YARP_BEGIN_PACK
Starts 1 byte packing for structs/classes.
Definition: system.h:204
* 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:219
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:264
#define YARP_UNUSED(var)
Definition: api.h:112
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