Nsound  0.9.4
Wavefile.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Wavefile.cc 875 2014-09-27 22:25:13Z weegreenblobbie $
4 //
5 // Nsound is a C++ library and Python module for audio synthesis featuring
6 // dynamic digital filters. Nsound lets you easily shape waveforms and write
7 // to disk or plot them. Nsound aims to be as powerful as Csound but easy to
8 // use.
9 //
10 // Copyright (c) 2004-2006 Nick Hilton
11 //
12 // weegreenblobbie_yahoo_com (replace '_' with '@' and '.')
13 //
14 //-----------------------------------------------------------------------------
15 
16 //-----------------------------------------------------------------------------
17 //
18 // This program is free software; you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation; either version 2 of the License, or
21 // (at your option) any later version.
22 //
23 // This program is distributed in the hope that it will be useful,
24 // but WITHOUT ANY WARRANTY; without even the implied warranty of
25 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 // GNU Library General Public License for more details.
27 //
28 // You should have received a copy of the GNU General Public License
29 // along with this program; if not, write to the Free Software
30 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 //
32 //-----------------------------------------------------------------------------
33 
34 #include <Nsound/Nsound.h>
35 
36 #include <Nsound/AudioStream.h>
37 #include <Nsound/Buffer.h>
38 #include <Nsound/Wavefile.h>
39 
40 #include <math.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <fstream>
44 #include <iostream>
45 #include <sstream>
46 
47 using std::cerr;
48 using std::endl;
49 using std::ifstream;
50 using std::ios_base;
51 using std::ofstream;
52 using std::string;
53 using std::stringstream;
54 
55 using namespace Nsound;
56 
57 const raw_float64 Wavefile::SIGNED_64_BIT_ = 9223372036854775807.0;
58 const raw_float64 Wavefile::SIGNED_48_BIT_ = 140737488355327.0;
59 const raw_float64 Wavefile::SIGNED_32_BIT_ = 2147483647.0;
60 const raw_float64 Wavefile::SIGNED_24_BIT_ = 8388607.0;
63 
67 
68 void
71 {
72  M_ASSERT_VALUE(rate, >, 0);
73 
74  default_sample_rate_ = rate;
75 }
76 
77 void
80 {
81  if(size == 64 ||
82  size == 48 ||
83  size == 32 ||
84  size == 24 ||
85  size == 16 ||
86  size == 8)
87  {
88  default_sample_size_ = size;
89  }
90  else
91  {
92  M_THROW("setDefaultSampleSize(): Can't use size " << size);
93  }
94 }
95 
96 void
98 setIEEEFloat(boolean flag)
99 {
100  if(flag)
101  {
103  if(default_sample_size_ > 32)
104  {
106  }
107  else
108  {
110  }
111  }
113 }
114 
115 void
118  const float64 & sample_rate,
119  const float64 & sample_bits,
120  const boolean & use_ieee_floats)
121 {
122  setDefaultSampleRate(sample_rate);
123  setDefaultSampleSize(static_cast<uint32>(sample_bits));
124  setIEEEFloat(use_ieee_floats);
125 }
126 
127 #ifdef __clang__
128  #pragma clang diagnostic push
129  #pragma clang diagnostic ignored "-Wunused-function"
130 #endif
131 
132 //-----------------------------------------------------------------------------
133 //
135 //
155 inline static
156 int64
158 {
159  int64 k = i;
160  uint8 * c = reinterpret_cast<uint8 *>(&k);
161 
162  // 0 1 2 3 4 5 6 7
163  // 0x1234567890abcdef
164  uint8 t = c[0];
165  c[0] = c[7];
166  c[7] = t;
167  t = c[1];
168  c[1] = c[6];
169  c[6] = t;
170  t = c[2];
171  c[2] = c[5];
172  c[5] = t;
173  t = c[3];
174  c[3] = c[4];
175  c[4] = t;
176 
177  return k;
178 };
179 
180 inline static
181 int64
183 {
184  int64 k = i;
185  uint8 * c = reinterpret_cast<uint8 *>(&k);
186 
187  // 0 1 2 3 4 5 6 7
188  // 0x1234567890abcdef
189 
190  uint8 t = c[2];
191  c[2] = c[7];
192  c[7] = t;
193  t = c[3];
194  c[3] = c[6];
195  c[6] = t;
196  t = c[4];
197  c[4] = c[5];
198  c[5] = t;
199 
200  return k;
201 };
202 
203 
204 inline static
205 int32
207 {
208  return static_cast<int32>(((i & 0xff000000) >> 24 |
209  ((i & 0x00ff0000) >> 8 |
210  ((i & 0x0000ff00) << 8 |
211  ((i & 0x000000ff) << 24)))));
212 };
213 
214 inline static
215 int32
217 {
218  return static_cast<int32>(((i & 0x00ff0000) >> 16 |
219  ((i & 0x0000ff00) |
220  ((i & 0x000000ff) << 16))));
221 };
222 
223 inline static
224 int32
226 {
227  return static_cast<int32>(((i & 0x0000ff00) >> 8 |
228  ((i & 0x000000ff) << 8)));
229 };
230 
231 #ifdef __clang__
232  #pragma clang diagnostic pop
233 #endif
234 
235 #ifdef NSOUND_PLATFORM_OS_WINDOWS
236  #define LM_UNUSED
237 #else
238  #define LM_UNUSED __attribute__((unused))
239 #endif
240 
241 //-----------------------------------------------------------------------------
244 inline static
245 int64
246 readInt(FILE * fd, uint32 n_bytes)
247 {
248  int64 temp64 = 0;
249 
250  size_t _ LM_UNUSED = fread(reinterpret_cast<char*>(&temp64), n_bytes, 1, fd);
251 
252  // Swap the bytes if we are on a big endian platform.
253  #ifdef NSOUND_BIG_ENDIAN
254  temp64 = swapBytesInt64(temp64);
255  #endif
256 
257  // Sign extend temp64.
258  switch(n_bytes)
259  {
260  // 48-bit
261  case 6:
262  if(temp64 & 0x0000800000000000ULL)
263  {
264  temp64 |= 0xffff000000000000ULL;
265  }
266  break;
267 
268  // 32-bit
269  case 4:
270  if(temp64 & 0x0000000080000000ULL)
271  {
272  temp64 |= 0xffffffff00000000ULL;
273  }
274  break;
275 
276  // 24-bit
277  case 3:
278  if(temp64 & 0x0000000000800000ULL)
279  {
280  temp64 |= 0xffffffffff000000ULL;
281  }
282  break;
283 
284  // 16-bit
285  case 2:
286  if(temp64 & 0x0000000000008000ULL)
287  {
288  temp64 |= 0xffffffffffff0000ULL;
289  }
290  break;
291 
292  // 8 bit wavefiles are stored unsigned (silly that it's different)
293  case 1:
294  break;
295  }
296 
297  return temp64;
298 }
299 
300 //-----------------------------------------------------------------------------
303 inline static
304 float32
305 readFloat32(FILE * fd)
306 {
307  int32 temp32 = 0;
308  float32 * f32 = reinterpret_cast<float32 *>(&temp32);
309 
310  size_t _ LM_UNUSED = fread(reinterpret_cast<char*>(&temp32), sizeof(float32), 1, fd);
311 
312  // Swap the bytes if we are on a big endian platform.
313  #ifdef NSOUND_BIG_ENDIAN
314  temp32 = swapBytesInt32(temp32);
315  #endif
316 
317  return *f32;
318 }
319 
320 //-----------------------------------------------------------------------------
323 inline static
324 float64
325 readFloat64(FILE * fd)
326 {
327  int64 temp64 = 0;
328  float64 * f64 = reinterpret_cast<float64 *>(&temp64);
329 
330  size_t _ LM_UNUSED = fread(reinterpret_cast<char*>(&temp64), sizeof(float64), 1, fd);
331 
332  // Swap the bytes if we are on a big endian platform.
333  #ifdef NSOUND_BIG_ENDIAN
334  if(sizeof(float64) == 8) temp64 = swapBytesInt64(temp64);
335  else if(sizeof(float64) == 4) temp64 = swapBytesInt32(temp64);
336  #endif
337 
338  return *f64;
339 }
340 
341 //-----------------------------------------------------------------------------
344 inline static
345 void
347  FILE * output,
348  uint32 n_bytes,
349  int64 value)
350 {
351  // Swap the bytes if we are on a big endian platform
352  #ifdef NSOUND_BIG_ENDIAN
353  value = swapBytesInt64(value);
354  #endif
355 
356  fwrite(reinterpret_cast<char*>(&value), n_bytes, 1, output);
357 }
358 
359 //-----------------------------------------------------------------------------
362 inline static
363 void
365  FILE * output,
366  float32 value)
367 {
368  // Swap the bytes if we are on a big endian platform
369  #ifdef NSOUND_BIG_ENDIAN
370  uint32 * v = reinterpret_cast<uint32 *>(&value);
371  *v = swapBytesInt32(*v);
372  #endif
373 
374  fwrite(reinterpret_cast<char*>(&value), 1, sizeof(float32), output);
375 }
376 
377 //-----------------------------------------------------------------------------
380 inline static
381 void
383  FILE * output,
384  float64 value)
385 {
386  // Swap the bytes if we are on a big endian platform
387  #ifdef NSOUND_BIG_ENDIAN
388  uint64 * v = reinterpret_cast<uint64 *>(&value);
389 
390  if(sizeof(float64) == 8) *v = swapBytesInt64(*v);
391  else if(sizeof(float64) == 4) *v = swapBytesInt32(*v);
392  #endif
393 
394  fwrite(reinterpret_cast<char*>(&value), sizeof(float64), 1, output);
395 }
396 
397 boolean
399 read(
400  const std::string & filename,
401  BufferPointerVector * b_vector,
402  AudioStream * as,
403  std::stringstream * ss)
404 {
405  FILE * fd;
406  fd = fopen(filename.c_str(), "rb");
407 
408  if(fd == NULL)
409  {
410  M_THROW("Wavefile::read(): unable to open file '" << filename << "'");
411 
412  return false;
413  }
414 
415  uint32 chunk_id = 0;
416  uint32 chunk_size = 0;
417 
418  // Read in RIFF header
419  chunk_id = static_cast<uint32>(readInt(fd,4));
420  if(chunk_id != Wavefile::RIFF_)
421  {
422  fclose(fd);
423 
424  M_THROW("Wavefile::read(): '" << filename
425  << "', could not read 'RIFF' from file");
426 
427  return false;
428  }
429 
430  // Read in RIFF chunk length
431  uint32 riff_chunk_length = static_cast<uint32>(readInt(fd,4));
432 
433  // Read in 'WAVE'
434  chunk_id = static_cast<uint32>(readInt(fd,4));
435 
436  if(chunk_id != Wavefile::WAVE_)
437  {
438  fclose(fd);
439 
440  M_THROW(
441  "Wavefile::read(): '" << filename
442  << "', could not read 'WAVE' from file");
443 
444  return false;
445  }
446 
447  // Determine end of file position.
448 
449  size_t cur_pos = ftell(fd);
450  fseek(fd, 0, SEEK_END);
451  size_t end_pos = ftell(fd);
452 
453  // Seek back to where we were.
454  #ifdef NSOUND_PLATFORM_OS_WINDOWS
455  fseek(fd, static_cast<long>(cur_pos), SEEK_SET);
456  #else
457  fseek(fd, cur_pos, SEEK_SET);
458  #endif
459 
460  // Read in chunk ids until we find the data chunk, skipping all other chunk
461  // ids except for the format chunk.
462 
463  uint16 format_tag = 0;
464  uint16 channels = 0;
465  uint32 sample_rate = 0;
466  uint32 average_bytes_per_second = 0;
467  uint32 block_alignment = 0;
468  uint32 bits_per_sample = 0;
469 
470  chunk_id = static_cast<uint32>(readInt(fd, 4));
471 
472  while(chunk_id != Wavefile::DATA_)
473  {
474  chunk_size = static_cast<uint32>(readInt(fd, 4));
475 
476  if(chunk_id == Wavefile::FMT_)
477  {
478  // Save the current postion.
479  size_t pos = ftell(fd);
480 
481  format_tag = static_cast<uint16>(readInt(fd, 2));
482  channels = static_cast<uint16>(readInt(fd, 2));
483  sample_rate = static_cast<uint32>(readInt(fd, 4));
484  average_bytes_per_second = static_cast<uint32>(readInt(fd, 4));
485  block_alignment = static_cast<uint32>(readInt(fd, 2));
486  bits_per_sample = static_cast<uint32>(readInt(fd, 2));
487 
488  #ifdef NSOUND_PLATFORM_OS_WINDOWS
489  fseek(fd, static_cast<long>(pos + static_cast<size_t>(chunk_size)), SEEK_SET);
490  #else
491  fseek(fd, pos + static_cast<size_t>(chunk_size), SEEK_SET);
492  #endif
493  }
494  else
495  {
496  // Seek over chunk.
497  fseek(fd, chunk_size, SEEK_CUR);
498  }
499 
500  // Read in next chunk id
501  chunk_id = static_cast<uint32>(readInt(fd, 4));
502 
503  cur_pos = ftell(fd);
504 
505  if(cur_pos >= end_pos)
506  {
507  fclose(fd);
508 
509  M_THROW("Wavefile::read(): '"
510  << filename
511  << "', reached end of file before finding the "
512  << "'data' chunk");
513 
514  return false;
515  }
516  }
517 
518  // Data length
519  uint32 data_length = static_cast<uint32>(readInt(fd, 4));
520 
521  // Determine data_length by using fseek.
522  cur_pos = ftell(fd);
523 
524  if(data_length > (end_pos - cur_pos))
525  {
526  cerr << WARNING_HEADER
527  << "the data chunk size indicates the file is truncated!" << endl
528  << " data_chunk_size = " << data_length << endl
529  << " actual data size = " << (end_pos - cur_pos) << endl;
530  }
531 
532  boolean fmt_found = true;
533 
534  if(data_length == 0)
535  {
536  M_THROW("Wavefile::read(): '"
537  << filename
538  << "', data length is zero!");
539 
540  fmt_found = false;
541  }
542 
543  if(channels == 0)
544  {
545  M_THROW("Wavefile::read(): '"
546  << filename
547  << "', channels is zero!");
548 
549  fmt_found = false;
550  }
551 
552  if(bits_per_sample == 0)
553  {
554  M_THROW("Wavefile::read(): '"
555  << filename
556  << "', bits_per_sample is zero!");
557 
558  fmt_found = false;
559  }
560 
561  uint32 n_samples = 0;
562 
563  if(fmt_found)
564  {
565  n_samples = data_length / channels / (bits_per_sample / 8);
566  }
567 
568  if(ss != NULL)
569  {
570  *ss << "'"
571  << filename
572  << "'"
573  << endl
574 
575  << "['RIFF'] = ['RIFF']"
576  << endl
577 
578  << "[riff_chunk_length] = ["
579  << riff_chunk_length
580  << "]"
581  << endl
582 
583  << "['WAVE'] = ['WAVE']"
584  << endl
585 
586  << "['fmt '] = ['fmt ']"
587  << endl
588 
589  << "[format_tag] = ["
590  << decodeFormatTag(format_tag)
591  << " ("
592  << format_tag
593  << ")]"
594  << endl
595 
596  << "[channels] = ["
597  << channels
598  << "]"
599  << endl
600 
601  << "[sample_rate] = ["
602  << sample_rate
603  << "]"
604  << endl
605 
606  << "[bytes_per_second] = ["
607  << average_bytes_per_second
608  << "]"
609  << endl
610 
611  << "[block_alignment] = ["
612  << block_alignment
613  << "]"
614  << endl
615 
616  << "[bits_per_sample] = ["
617  << bits_per_sample
618  << "]"
619  << endl
620 
621  << "['data'] = ['data']"
622  << endl
623 
624  << "[data_length_bytes] = ["
625  << data_length
626  << "]"
627  << endl
628 
629  << "[data_length_samples] = [";
630 
631  if(fmt_found)
632  {
633  *ss << n_samples
634  << "]"
635  << endl
636  << "[data_length_seconds] = ["
637  << (static_cast<float32>(n_samples) /
638  static_cast<float32>(sample_rate))
639  << "]"
640  << endl;
641  }
642  else
643  {
644  *ss << "unknown!"
645  << "]"
646  << endl
647  << "[data_length_seconds] = [unknown!]"
648  << endl;
649  }
650  }
651 
652  if(!fmt_found)
653  {
654  fclose(fd);
655  return false;
656  }
657 
658  // Check if the format is PCM or IEEE Float
659  if( format_tag != Wavefile::WAVE_FORMAT_PCM_ &&
660  format_tag != Wavefile::WAVE_FORMAT_IEEE_FLOAT_)
661  {
662  fclose(fd);
663 
664  M_THROW("Wavefile::read(): '"
665  << filename
666  << "', Nsound currently only supports PCM and IEEE Floating "
667  << "Point formats, not '"
668  << decodeFormatTag(format_tag)
669  << "'");
670 
671  return false;
672  }
673 
675  // set data sizes
676  uint32 n_bytes = 0;
677 // raw_uint64 max_sample;
678  raw_float64 data_scale = static_cast<float64>(0.0);
679  switch(bits_per_sample)
680  {
681  case 64:
682  {
683  n_bytes = 8;
684  data_scale = Wavefile::SIGNED_64_BIT_;
685 // max_sample = Wavefile::UNSIGNED_64_BIT_;
686  break;
687  }
688  case 48:
689  {
690  n_bytes = 6;
691  data_scale = Wavefile::SIGNED_48_BIT_;
692 // max_sample = Wavefile::UNSIGNED_48_BIT_;
693  break;
694  }
695  case 32:
696  {
697  n_bytes = 4;
698  data_scale = Wavefile::SIGNED_32_BIT_;
699 // max_sample = Wavefile::UNSIGNED_32_BIT_;
700  break;
701  }
702  case 24:
703  {
704  n_bytes = 3;
705  data_scale = Wavefile::SIGNED_24_BIT_;
706 // max_sample = Wavefile::UNSIGNED_24_BIT_;
707  break;
708  }
709  case 16:
710  {
711  n_bytes = 2;
712  data_scale = Wavefile::SIGNED_16_BIT_;
713 // max_sample = Wavefile::UNSIGNED_16_BIT_;
714  break;
715  }
716  case 8:
717  {
718  n_bytes = 1;
719  data_scale = Wavefile::SIGNED_8_BIT_;
720 // max_sample = Wavefile::UNSIGNED_8_BIT_;
721  break;
722  }
723  default:
724  fclose(fd);
725 
726  M_THROW("Wavefile::read(): bits_per_sample = "
727  << bits_per_sample);
728 
729  return false;
730  }
731 
733  // Read the pulse code modulation (PCM) data.
734 
735  // If we are only doing a readHeader.
736  if(ss != NULL)
737  {
738  // Only read and print out 10 samples per channel.
739  if(n_samples > 10)
740  {
741  n_samples = 10;
742  }
743 
744  BufferVector bv;
745 
746  // Init BufferVector.
747  for(uint32 ch = 0; ch < channels; ++ch)
748  {
749  bv.push_back(Buffer(10));
750 
751  bool format_mismatch = false;
752 
753  // Read the audio samples without scaling them.
754  for(uint32 i = 0; i < n_samples; ++i)
755  {
756  if(format_tag == WAVE_FORMAT_PCM_)
757  {
758  bv[ch] << static_cast<float64>(readInt(fd,n_bytes));
759  }
760  else if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
761  {
762  if(bits_per_sample == 32)
763  {
764  bv[ch] << static_cast<float64>(readFloat32(fd));
765  }
766  else if(bits_per_sample == 64)
767  {
768  bv[ch] << readFloat64(fd);
769  }
770  else
771  {
772  format_mismatch = true;
773  }
774  }
775  }
776 
777  if(format_mismatch)
778  {
779  (*ss)
780  << "Wavefile::read(\""
781  << filename
782  << "\"): format is "
783  << "IEEE Float but bits_per_sample = "
784  << bits_per_sample;
785  return false;
786  }
787 
788  // Print out the results.
789  (*ss) << "channel[" << ch << "] = ";
790 
791  for(uint32 i = 0; i < n_samples; ++i)
792  {
793  (*ss) << bv[ch][i];
794  (*ss) << " ";
795  }
796 
797  (*ss) << endl;
798  }
799  }
800 
801  // If we are really reading in the data.
802  else if(b_vector != NULL)
803  {
804  int64 sample;
805  for(uint32 i = 0; i < n_samples; ++i)
806  {
807  // Two cases.
808  //
809  // Case 1: there are less channels in the file than Buffers in
810  // b_vector
811  //
812  // Case 2: there are greater than or equal number of channels in
813  // the file as there are Buffers in b_vector
814 
815  uint32 channels_to_store = static_cast<uint32>(b_vector->size());
816 
817  if(channels < channels_to_store)
818  {
819  channels_to_store = channels;
820  }
821 
822  // Read data into buffers stored in b_vector.
823  for(uint32 ch = 0; ch < channels_to_store; ++ch)
824  {
825  if(format_tag == WAVE_FORMAT_PCM_)
826  {
827  sample = readInt(fd,n_bytes);
828 
829  if(bits_per_sample == 8)
830  {
831  sample -= 127;
832  }
833 
834  *((*b_vector)[ch]) << static_cast<float64>(sample)
835  / data_scale;
836  }
837  else if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
838  {
839  if(bits_per_sample == 32)
840  {
841  *((*b_vector)[ch]) << static_cast<float64>(
842  readFloat32(fd));
843  }
844  else if(bits_per_sample == 64)
845  {
846  *((*b_vector)[ch]) << readFloat64(fd);
847  }
848  else
849  {
850  M_THROW("Wavefile::read(): format is "
851  << "IEEE Float but bits_per_sample = "
852  << bits_per_sample);
853  }
854  }
855  }
856 
857  // Skip data in other channels.
858  for(uint32 ch = channels_to_store; ch < channels; ++ch)
859  {
860  readInt(fd, n_bytes);
861  }
862  }
863  }
864  else if(as != NULL)
865  {
866  int64 sample;
867  as->setSampleRate(sample_rate);
868  as->setNChannels(channels);
869 
870  for(uint32 i = 0; i < n_samples; ++i)
871  {
872  // Read data into buffers stored in b_vector.
873  for(uint32 ch = 0; ch < channels; ++ch)
874  {
875  if(format_tag == WAVE_FORMAT_PCM_)
876  {
877  sample = readInt(fd,n_bytes);
878 
879  if(bits_per_sample == 8)
880  {
881  sample -= 127;
882  }
883 
884  (*as)[ch] << static_cast<float64>(sample) / data_scale;
885  }
886  else if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
887  {
888  if(bits_per_sample == 32)
889  {
890  (*as)[ch] << static_cast<float64>(readFloat32(fd));
891  }
892  else if(bits_per_sample == 64)
893  {
894  (*as)[ch] << readFloat64(fd);
895  }
896  else
897  {
898  M_THROW("Wavefile::read(): format is "
899  << "IEEE Float but bits_per_sample = "
900  << bits_per_sample);
901  }
902  }
903  }
904  }
905  }
906  else
907  {
908  fclose(fd);
909  M_THROW("Wavefile::read(): unhandled case!");
910  return false;
911  }
912 
913  fclose(fd);
914 
915  return true;
916 }
917 
918 boolean
920 read(const std::string & filename, AudioStream & as)
921 {
922  boolean was_successful = read(filename, NULL, &as, NULL);
923 
924  return was_successful;
925 }
926 
927 //-----------------------------------------------------------------------------
928 // readHeader(string filename)
929 //
930 // This method opens the wavefile specified by filename and prints the
931 // contents of the RIFF header and the first 5 samples.
932 boolean
935  const std::string & filename,
936  std::string & info)
937 {
938  std::stringstream ss;
939  boolean success = Wavefile::read(filename, NULL, NULL, &ss);
940  info = ss.str();
941  return success;
942 }
943 
945 // write(string filename, AudioStream as)
946 //
947 // This method writes pulse code modulation (PCM) to the file
948 // specified by filename. If filename exists already, it will be
949 // overwritten.
950 boolean
952 write(const string & filename,
953  const AudioStream & as,
954  uint32 bits_per_sample)
955 {
956  if( bits_per_sample != 8 &&
957  bits_per_sample != 16 &&
958  bits_per_sample != 24 &&
959  bits_per_sample != 32 &&
960  bits_per_sample != 48 &&
961  bits_per_sample != 64)
962  {
963  M_THROW("Wavefile::write(): "
964  << "bits per sample must be 8, 16, 24, 32, 48, 64");
965  return false;
966  }
967 
968  // open the file
969  FILE * output;
970  output = fopen(filename.c_str(), "wb");
971 
972  if(output == NULL)
973  {
974  M_THROW("Wavefile::write(): "
975  << "unable to open file '"
976  << filename);
977  return false;
978  }
979 
980  // verify channels_
981  uint32 channels = as.getNChannels();
982 
983  uint32 n_samples = as.getLength();
984 
985  // The data length is the total number of bytes of the raw sound
986  // data. There are 8 bits per byte.
987  uint32 data_length = n_samples * channels * (bits_per_sample / 8);
988 
989  // riff_chunk_lenth is always 36 bytes larger than the data length,
990  // the 36 bytes is added to include all the header information for
991  // the riff wavefile. Take a look at Wavefile.hxx to see a block
992  // diagram of the header format.
993  uint32 riff_chunk_length = data_length + 36;
994 
995  // calculate block_alignemnt
996  uint32 block_alignment = channels * (bits_per_sample / 8);
997 
998  // calculate bytes_per_second
999  uint32 sample_rate = static_cast<uint32>(as.getSampleRate());
1000  uint32 bytes_per_second = sample_rate * block_alignment;
1001 
1003 
1005  // Write out the data
1006 
1007  writeInt(output,4,Wavefile::RIFF_);
1008  writeInt(output,4,riff_chunk_length);
1009  writeInt(output,4,Wavefile::WAVE_);
1010  writeInt(output,4,Wavefile::FMT_);
1011  writeInt(output,4,16); // format_chunk_length = 16
1012  writeInt(output,2,format_tag);
1013  writeInt(output,2,channels);
1014  writeInt(output,4,sample_rate);
1015  writeInt(output,4,bytes_per_second);
1016  writeInt(output,2,block_alignment);
1017  writeInt(output,2,bits_per_sample);
1018 
1019  if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
1020  {
1021  writeInt(output,4,Wavefile::FACT_);
1022  writeInt(output,4, 4);
1023  writeInt(output,4, n_samples);
1024 
1025  writeInt(output,4,Wavefile::PEAK_);
1026  writeInt(output,4, 16);
1027  writeInt(output,4, 0);
1028  writeInt(output,4, 0);
1029  writeInt(output,4, 0);
1030  writeInt(output,4, 0);
1031  }
1032 
1033  writeInt(output,4,Wavefile::DATA_);
1034  writeInt(output,4,data_length);
1035 
1037  // set data sizes
1038  uint32 n_bytes = 0;
1039  float64 data_scale = static_cast<float64>(0.0);
1040  switch(bits_per_sample)
1041  {
1042  case 64:
1043  {
1044  n_bytes = 8;
1045  data_scale = Wavefile::SIGNED_64_BIT_;
1046  break;
1047  }
1048  case 48:
1049  {
1050  n_bytes = 6;
1051  data_scale = Wavefile::SIGNED_48_BIT_;
1052  break;
1053  }
1054  case 32:
1055  {
1056  n_bytes = 4;
1057  data_scale = Wavefile::SIGNED_32_BIT_;
1058  break;
1059  }
1060  case 24:
1061  {
1062  n_bytes = 3;
1063  data_scale = Wavefile::SIGNED_24_BIT_;
1064  break;
1065  }
1066  case 16:
1067  {
1068  n_bytes = 2;
1069  data_scale = Wavefile::SIGNED_16_BIT_;
1070  break;
1071  }
1072  case 8:
1073  {
1074  n_bytes = 1;
1075  data_scale = Wavefile::SIGNED_8_BIT_;
1076  break;
1077  }
1078  }
1079 
1080  // write the data
1081  int64 scaled = 0;
1082  int64 positive_data_scale = static_cast<int64>(data_scale);
1083  int64 negitive_data_scale = static_cast<int64>(-1.0 * data_scale);
1084 
1085  for(uint32 i = 0; i < n_samples; i++)
1086  {
1087  for(uint32 ch = 0; ch < channels; ++ch)
1088  {
1089  if(format_tag == WAVE_FORMAT_PCM_)
1090  {
1091  scaled = static_cast<int64>(as[ch][i] * data_scale);
1092 
1093  if(scaled > positive_data_scale)
1094  {
1095  scaled = positive_data_scale;
1096  }
1097  else if(scaled < negitive_data_scale)
1098  {
1099  scaled = negitive_data_scale;
1100  }
1101  writeInt(output,n_bytes,scaled);
1102  }
1103  else if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
1104  {
1105  if(bits_per_sample == 32)
1106  {
1107  writeFloat32(output, static_cast<float32>(as[ch][i]));
1108  }
1109  else if(bits_per_sample == 64)
1110  {
1111  writeFloat64(output, as[ch][i]);
1112  }
1113  else
1114  {
1115  M_THROW(
1116  "Wavefile::read(\""
1117  << filename
1118  << "\"): format is "
1119  << "IEEE Float but bits_per_sample = "
1120  << bits_per_sample);
1121  }
1122  }
1123  }
1124  }
1125 
1126  fclose(output);
1127  return true;
1128 }
1129 
1130 boolean
1131 Wavefile::
1133  const string & filename,
1134  const Buffer & buffer,
1135  uint32 bits_per_sample,
1136  uint32 sample_rate)
1137 {
1138  if( bits_per_sample != 8 &&
1139  bits_per_sample != 16 &&
1140  bits_per_sample != 24 &&
1141  bits_per_sample != 32 &&
1142  bits_per_sample != 48 &&
1143  bits_per_sample != 64)
1144  {
1145  M_THROW("Wavefile::write(): "
1146  << "bits per sample must be 8, 16, 24, 32, 64");
1147  return false;
1148  }
1149 
1150  // open the file
1151 
1152  FILE * output;
1153  output = fopen(filename.c_str(), "wb");
1154  if(output == NULL)
1155  {
1156  M_THROW("Wavefile::write(): "
1157  << "unable to open file '"
1158  << filename);
1159  return false;
1160  }
1161 
1162  // verify channels_
1163  uint32 channels = 1;
1164 
1165  uint32 n_samples = buffer.getLength();
1166 
1167  // The data length is the total number of bytes of the raw sound
1168  // data. There are 8 bits per byte.
1169  uint32 data_length = n_samples * channels * (bits_per_sample / 8);
1170 
1171  // riff_chunk_lenth is always 36 bytes larger than the data length,
1172  // the 36 bytes is added to include all the header information for
1173  // the riff wavefile. Take a look at Wavefile.hxx to see a block
1174  // diagram of the header format.
1175  uint32 riff_chunk_length = data_length + 36;
1176 
1177  // calculate block_alignemnt
1178  uint32 block_alignment = channels * (bits_per_sample / 8);
1179 
1180  // calculate bytes_per_second
1181  uint32 bytes_per_second = sample_rate * block_alignment;
1182 
1184 
1186  // Write out the data
1187 
1188  writeInt(output,4,Wavefile::RIFF_);
1189  writeInt(output,4,riff_chunk_length);
1190  writeInt(output,4,Wavefile::WAVE_);
1191  writeInt(output,4,Wavefile::FMT_);
1192  writeInt(output,4,16); // format_chunk_length = 16
1193  writeInt(output,2,format_tag);
1194  writeInt(output,2,channels);
1195  writeInt(output,4,sample_rate);
1196  writeInt(output,4,bytes_per_second);
1197  writeInt(output,2,block_alignment);
1198  writeInt(output,2,bits_per_sample);
1199 
1200  if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
1201  {
1202  writeInt(output,4,Wavefile::FACT_);
1203  writeInt(output,4, 4);
1204  writeInt(output,4, n_samples);
1205 
1206  writeInt(output,4,Wavefile::PEAK_);
1207  writeInt(output,4, 16);
1208  writeInt(output,4, 0);
1209  writeInt(output,4, 0);
1210  writeInt(output,4, 0);
1211  writeInt(output,4, 0);
1212  }
1213 
1214  writeInt(output,4,Wavefile::DATA_);
1215  writeInt(output,4,data_length);
1216 
1218  // set data sizes
1219  uint32 n_bytes = 0;
1220  float64 data_scale = static_cast<float64>(0.0);
1221  switch(bits_per_sample)
1222  {
1223  case 64:
1224  {
1225  n_bytes = 8;
1226  data_scale = Wavefile::SIGNED_64_BIT_;
1227  break;
1228  }
1229  case 48:
1230  {
1231  n_bytes = 6;
1232  data_scale = Wavefile::SIGNED_48_BIT_;
1233  break;
1234  }
1235  case 32:
1236  {
1237  n_bytes = 4;
1238  data_scale = Wavefile::SIGNED_32_BIT_;
1239  break;
1240  }
1241  case 24:
1242  {
1243  n_bytes = 3;
1244  data_scale = Wavefile::SIGNED_24_BIT_;
1245  break;
1246  }
1247  case 16:
1248  {
1249  n_bytes = 2;
1250  data_scale = Wavefile::SIGNED_16_BIT_;
1251  break;
1252  }
1253  case 8:
1254  {
1255  n_bytes = 1;
1256  data_scale = Wavefile::SIGNED_8_BIT_;
1257  break;
1258  }
1259  }
1260 
1262  // write the data
1263  int64 scaled;
1264  int64 positive_data_scale = static_cast<int64>(data_scale);
1265  int64 negitive_data_scale = static_cast<int64>(-1.0 * data_scale);
1266 
1267  for(uint32 i = 0; i < n_samples; ++i)
1268  {
1269  if(format_tag == WAVE_FORMAT_PCM_)
1270  {
1271  scaled = static_cast<int64>(buffer[i] * data_scale);
1272 
1273  if(scaled > positive_data_scale)
1274  {
1275  scaled = positive_data_scale;
1276  }
1277  else if(scaled < negitive_data_scale)
1278  {
1279  scaled = negitive_data_scale;
1280  }
1281  writeInt(output,n_bytes,scaled);
1282  }
1283  else if(format_tag == WAVE_FORMAT_IEEE_FLOAT_)
1284  {
1285  if(bits_per_sample == 32)
1286  {
1287  writeFloat32(output, static_cast<float32>(buffer[i]));
1288  }
1289  else if(bits_per_sample == 64)
1290  {
1291  writeFloat64(output, buffer[i]);
1292  }
1293  else
1294  {
1295  M_THROW("Wavefile::read(): format is "
1296  << "IEEE Float but bits_per_sample = "
1297  << bits_per_sample);
1298  }
1299  }
1300  }
1301 
1302  fclose(output);
1303  return true;
1304 }
1305 
1306 //-----------------------------------------------------------------------------
1307 std::string
1308 Wavefile::
1309 decodeFormatTag(const uint16 format_tag)
1310 {
1311  switch(format_tag)
1312  {
1313  case 0x0000: return "Unknown";
1314  case 0x0001: return "Microsoft PCM";
1315  case 0x0002: return "Microsoft ADPCM";
1316  case 0x0003: return "IEEE Float";
1317  case 0x0004: return "Compaq VSELP";
1318  case 0x0005: return "IBM CVSD";
1319  case 0x0006: return "Microsoft ALAW";
1320  case 0x0007: return "Microsoft MULAW";
1321  case 0x000A: return "Microsoft Windows Media Audio Speech";
1322  case 0x0010: return "OKI ADPCM";
1323  case 0x0011: return "Intel DVI ADPCM";
1324  case 0x0012: return "Videologic MediaSpace ADPCM";
1325  case 0x0013: return "Sierra ADPCM";
1326  case 0x0014: return "Antex Electronics G.723 ADPCM";
1327  case 0x0015: return "DSP Solution DIGISTD";
1328  case 0x0016: return "DSP Solution DIGIFIX";
1329  case 0x0017: return "Dialogic OKI ADPCM";
1330  case 0x0018: return "MediaVision ADPCM";
1331  case 0x0019: return "HP CU";
1332  case 0x0020: return "Yamaha ADPCM";
1333  case 0x0021: return "Speech Compression Sonarc";
1334  case 0x0022: return "DSP Group True Speech";
1335  case 0x0023: return "Echo Speech EchoSC1";
1336  case 0x0024: return "Audiofile AF36";
1337  case 0x0025: return "APTX";
1338  case 0x0026: return "AudioFile AF10";
1339  case 0x0027: return "Prosody 1612";
1340  case 0x0028: return "LRC";
1341  case 0x0030: return "Dolby AC2";
1342  case 0x0031: return "Microsoft GSM610";
1343  case 0x0032: return "Microsoft MSNAudio";
1344  case 0x0033: return "Antex ADPCME";
1345  case 0x0034: return "Control Res VQLPC";
1346  case 0x0035: return "Digireal";
1347  case 0x0036: return "DigiADPCM AC2";
1348  case 0x0037: return "Control Res CR10";
1349  case 0x0038: return "NMS VBXADPCM AC2";
1350  case 0x0039: return "Roland RDAC";
1351  case 0x003A: return "EchoSC3";
1352  case 0x003B: return "Rockwell ADPCM";
1353  case 0x003C: return "Rockwell Digit LK";
1354  case 0x003D: return "Xebec";
1355  case 0x0040: return "Antex Electronics G.721";
1356  case 0x0041: return "Antex Electronics G.728 CELP";
1357  case 0x0042: return "Microsoft MSG723";
1358  case 0x0050: return "MPEG";
1359  case 0x0052: return "Voxware RT24";
1360  case 0x0053: return "InSoft PAC";
1361  case 0x0055: return "MPEG Layer 3";
1362  case 0x0057: return "AMR NB";
1363  case 0x0058: return "AMR WB";
1364  case 0x0059: return "Lucent G.723";
1365  case 0x0060: return "Cirrus";
1366  case 0x0061: return "ESPCM";
1367  case 0x0062: return "Voxware";
1368  case 0x0063: return "Canopus Atrac";
1369  case 0x0064: return "APICOM G.726 ADPCM";
1370  case 0x0065: return "APICOM G.722 ADPCM";
1371  case 0x0066: return "Microsoft DSAT";
1372  case 0x0067: return "Microsoft DSAT Display";
1373  case 0x0069: return "Voxware Byte Aligned";
1374  case 0x0070: return "Voxware AC8";
1375  case 0x0071: return "Voxware AC10";
1376  case 0x0072: return "Voxware AC16";
1377  case 0x0073: return "Voxware AC20";
1378  case 0x0074: return "Voxware Metavoice";
1379  case 0x0075: return "Voxware Metasound";
1380  case 0x0076: return "Voxware RT29HW";
1381  case 0x0077: return "Voxware VR12";
1382  case 0x0078: return "Voxware VR18";
1383  case 0x0079: return "Voxware TQ40";
1384  case 0x0080: return "Softsound";
1385  case 0x0081: return "Voxware TQ60";
1386  case 0x0082: return "MSRT24";
1387  case 0x0083: return "AT&T G.729A";
1388  case 0x0084: return "Motion Pixels MVI MV12";
1389  case 0x0085: return "DF G.726";
1390  case 0x0086: return "DF GSM610";
1391  case 0x0088: return "ISIAudio";
1392  case 0x0089: return "Onlive";
1393  case 0x0091: return "Siemens SBC24";
1394  case 0x0092: return "Dolby AC3 SPDIF";
1395  case 0x0093: return "Mediasonic G723";
1396  case 0x0094: return "Prosody 8KBPS";
1397  case 0x0097: return "ZyXEL ADPCM";
1398  case 0x0098: return "Philips LPCBB";
1399  case 0x0099: return "Packed";
1400  case 0x00A0: return "Malden PhonyTalk";
1401  case 0x00FF: return "AAC";
1402  case 0x0100: return "Rhetorex ADPCM";
1403  case 0x0101: return "IBM MULAW";
1404  case 0x0102: return "IBM ALAW";
1405  case 0x0103: return "IBM ADPCM";
1406  case 0x0111: return "Vivo G.723";
1407  case 0x0112: return "Vivo Siren";
1408  case 0x0123: return "DEC G.723";
1409  case 0x0125: return "Sanyo LD ADPCM";
1410  case 0x0130: return "Siprolab ACEPLNET";
1411  case 0x0131: return "Siprolab ACELP4800";
1412  case 0x0132: return "Siprolab ACELP8V3";
1413  case 0x0133: return "Siprolab G729";
1414  case 0x0134: return "Siprolab G729A";
1415  case 0x0135: return "Siprolab Kelvin";
1416  case 0x0140: return "G726 ADPCM";
1417  case 0x0150: return "Qualcomm Purevoice";
1418  case 0x0151: return "Qualcomm Halfrate";
1419  case 0x0155: return "Tub GSM";
1420  case 0x0160: return "WMAV1";
1421  case 0x0161: return "WMAV2";
1422  case 0x0162: return "WMAV3";
1423  case 0x0163: return "WMAV3 L";
1424  case 0x0200: return "Creative ADPCM";
1425  case 0x0202: return "Creative FastSpeech8";
1426  case 0x0203: return "Creative FastSpeech10";
1427  case 0x0210: return "UHER ADPCM";
1428  case 0x0220: return "Quarterdeck";
1429  case 0x0230: return "iLink VC";
1430  case 0x0240: return "Raw Sport";
1431  case 0x0250: return "IPI HSX";
1432  case 0x0251: return "IPI RPELP";
1433  case 0x0260: return "CS2";
1434  case 0x0270: return "Sony ATRAC3";
1435  case 0x028E: return "Siren";
1436  case 0x0300: return "Fujitsu FM Towns Snd";
1437  case 0x0400: return "BTV Digital";
1438  case 0x0401: return "IMC";
1439  case 0x0450: return "QDesign Music";
1440  case 0x0680: return "AT&T VME VMPCM";
1441  case 0x0681: return "TCP";
1442  case 0x1000: return "Olivetti OLIGSM";
1443  case 0x1001: return "Olivetti OLIADPCM";
1444  case 0x1002: return "Olivetti OLICELP";
1445  case 0x1003: return "Olivetti OLISBC";
1446  case 0x1004: return "Olivetti OLIOPR";
1447  case 0x1100: return "LH Codec";
1448  case 0x1400: return "Norris";
1449  case 0x1401: return "AT&T ISIAudio";
1450  case 0x1500: return "AT&T Soundspace Music Compression";
1451  case 0x2000: return "DVM";
1452  case 0x2001: return "DTS";
1453  case 0x2048: return "Sonic";
1454  case 0x4143: return "AAC AC";
1455  case 0x674f: return "Vorbis 1";
1456  case 0x6750: return "Vorbis 2";
1457  case 0x6751: return "Vorbis 3";
1458  case 0x676f: return "Vorbis 1+";
1459  case 0x6770: return "Vorbis 2+";
1460  case 0x6771: return "Vorbis 3+";
1461  case 0x706d: return "AAC PM";
1462  case 0x7A21: return "GSM AMR CBR";
1463  case 0x7A22: return "GSM AMR VBR";
1464  case 0xF1AC: return "FLAC";
1465  case 0xFFFE: return "WAVE_FORMAT_EXTENSIBLE";
1466  case 0xFFFF: return "Experimental";
1467  }
1468 
1469  return "UNKOWN";
1470 }
1471 
1472 //-----------------------------------------------------------------------------
1473 Buffer &
1474 Nsound::
1475 operator<<(Buffer & lhs, const char * rhs)
1476 {
1477  BufferPointerVector b_vector;
1478 
1479  b_vector.push_back(&lhs);
1480 
1481  Wavefile::read(rhs,&b_vector, NULL, NULL);
1482 
1483  return lhs;
1484 }
1485 
1486 void
1487 Nsound::
1488 operator>>(const Buffer & lhs, const char * rhs)
1489 {
1491  rhs,
1492  lhs,
1495 }
1496 
1497 //-----------------------------------------------------------------------------
1498 AudioStream &
1499 Nsound::
1500 operator<<(AudioStream & lhs, const char * rhs)
1501 {
1502  Wavefile::read(rhs, NULL, &lhs, NULL);
1503 
1504  return lhs;
1505 }
1506 
1507 void
1508 Nsound::
1509 operator>>(const AudioStream & lhs, const char * rhs)
1510 {
1512  rhs,
1513  lhs,
1515 }
1516 
1517 //-----------------------------------------------------------------------------
1518 typedef struct RawTag
1519 {
1520  char header[3];
1521  char title[30];
1522  char artist[30];
1523  char album[30];
1524  char year[4];
1525  char comment[30];
1526  char genre;
1527 
1528 } RawTag;
1529 
1530 //-----------------------------------------------------------------------------
1531 ID3v1Tag::
1532 ID3v1Tag(const std::string & filename, boolean show_warnings)
1533  : title(),
1534  artist(),
1535  album(),
1536  year(),
1537  comment(),
1538  genre(' ')
1539 {
1540  if(filename.size() > 0)
1541  {
1542  this->read(filename,show_warnings);
1543  }
1544 }
1545 
1546 //-----------------------------------------------------------------------------
1547 // searches the file for ID3v1 'TAG', if it finds it, return the file position
1548 // where it is located, -1 if not found, -2 for all other errors.
1549 
1550 #define NOT_FOUND -1
1551 #define IO_ERROR -2
1552 
1553 int64
1554 findID3v1Tag(FILE * fin)
1555 {
1556  uint32 chunk_id = 0;
1557  uint32 header_limit = 72 ; // The 'data' should be near the begging
1558  // of the file if it is a WAVE file.
1559 
1560  size_t data_length = 0;
1561 
1562  uint32 count = 0;
1563 
1564  M_CHECK_PTR(fin);
1565  if(fin == NULL) return IO_ERROR;
1566 
1567  fseek(fin, 0, SEEK_SET);
1568 
1569  // Verify first tag is RIFF
1570  chunk_id = static_cast<uint32>(readInt(fin, 4));
1571  count += 4;
1572 
1573  if(chunk_id != Wavefile::RIFF_)
1574  {
1575  M_THROW("ID3v1Tag::find(): could not read 'RIFF' from file");
1576  return IO_ERROR;
1577  }
1578 
1579  // Read RIFF chunk length
1580  chunk_id = static_cast<uint32>(readInt(fin, 4));
1581  count += 4;
1582 
1583  // Read in 'WAVE'
1584  chunk_id = static_cast<uint32>(readInt(fin, 4));
1585  count += 4;
1586 
1587  if(chunk_id != Wavefile::WAVE_)
1588  {
1589  M_THROW("ID3v1Tag::find(): could not read 'WAVE' from file");
1590  return IO_ERROR;
1591  }
1592 
1593  // Okay, we now know we are reading a RIFF WAVE file.
1594 
1595  // Search for the 'data' tag.
1596  while(count < header_limit)
1597  {
1598  chunk_id = static_cast<uint32>(readInt(fin, 4));
1599 
1600  count += 4;
1601 
1602  if(chunk_id == Wavefile::DATA_)
1603  {
1604  data_length = static_cast<uint32>(readInt(fin,4));
1605  break;
1606  }
1607  }
1608 
1609  if(count >= header_limit)
1610  {
1611  cerr << "*** Error --> ID3v1Tag::find(): did not find the 'data'"
1612  << endl;
1613  return IO_ERROR;
1614  }
1615 
1616  size_t cur_pos = ftell(fin);
1617  fseek(fin, 0, SEEK_END);
1618  size_t end_pos = ftell(fin);
1619 
1620  // Seek to the end of the data
1621  #ifdef NSOUND_PLATFORM_OS_WINDOWS
1622  fseek(fin, static_cast<long>(cur_pos), SEEK_SET);
1623  fseek(fin, static_cast<long>(data_length), SEEK_CUR);
1624  #else
1625  fseek(fin, cur_pos, SEEK_SET);
1626  fseek(fin, data_length, SEEK_CUR);
1627  #endif
1628 
1629  // Start scanning for 'TAG'
1630  cur_pos = ftell(fin);
1631  while(cur_pos < end_pos-2)
1632  {
1633  char t[3];
1634 
1635  if(3 != fread(t, 1, 3, fin))
1636  {
1637  M_THROW("ID3v1Tag::find(): IO error reading file");
1638  return IO_ERROR;
1639  }
1640 
1641  if(t[0] == 'T' && t[1] == 'A' && t[2] == 'G')
1642  {
1643  break;
1644  }
1645 
1646  cur_pos = ftell(fin);
1647  }
1648 
1649  // No tag.
1650  if(cur_pos >= end_pos)
1651  {
1652  return NOT_FOUND;
1653  }
1654 
1655  // We have the tag, back up three bytes and return position.
1656  fseek(fin, -3, SEEK_CUR);
1657 
1658  return ftell(fin);
1659 }
1660 
1661 boolean
1662 ID3v1Tag::
1663 read(const std::string & filename, boolean show_warnings)
1664 {
1665  FILE * fin = fopen(filename.c_str(), "rb");
1666 
1667  if(fin == NULL)
1668  {
1669  M_THROW("ID3v1Tag::read(): could not open the file '"
1670  << filename
1671  << "'");
1672  return false;
1673  }
1674 
1675  int64 tag_pos = static_cast<size_t>(findID3v1Tag(fin));
1676 
1677  if(tag_pos == IO_ERROR)
1678  {
1679  fclose(fin);
1680  M_THROW("ID3v1Tag::read(): ID3v1Tag::find() failed!");
1681  return false;
1682  }
1683 
1684  if(tag_pos == NOT_FOUND && show_warnings)
1685  {
1686  fclose(fin);
1687  cerr << "*** Warning --> ID3v1Tag::read(): could not find the ID3v1 'TAG'"
1688  << endl;
1689  return false;
1690  }
1691 
1692  // Seek to the tag.
1693  #ifdef NSOUND_PLATFORM_OS_WINDOWS
1694  fseek(fin, static_cast<long>(tag_pos), SEEK_SET);
1695  #else
1696  fseek(fin, tag_pos, SEEK_SET);
1697  #endif
1698 
1699  RawTag tag;
1700 
1701  memset(reinterpret_cast<char *>(&tag), 0, sizeof(RawTag));
1702 
1703  // Read the tag.
1704  if(sizeof(RawTag) != fread(tag.header, 1, sizeof(RawTag), fin))
1705  {
1706  fclose(fin);
1707  cerr << "*** Error --> ID3v1Tag::read(): failed to read the ID3v1 TAG!"
1708  << endl;
1709  return false;
1710  }
1711 
1712  fclose(fin);
1713 
1714  this->title.clear();
1715  this->artist.clear();
1716  this->album.clear();
1717  this->year.clear();
1718  this->comment.clear();
1719  this->genre = ' ';
1720 
1721  // Title
1722  for(uint32 i = 0; i < 30; ++i)
1723  {
1724  if(tag.title[i] != '\0') this->title += tag.title[i];
1725  else break;
1726  }
1727 
1728  // Artist
1729  for(uint32 i = 0; i < 30; ++i)
1730  {
1731  if(tag.artist[i] != '\0') this->artist += tag.artist[i];
1732  else break;
1733  }
1734 
1735  // Album
1736  for(uint32 i = 0; i < 30; ++i)
1737  {
1738  if(tag.album[i] != '\0') this->album += tag.album[i];
1739  else break;
1740  }
1741 
1742  // Year
1743  for(uint32 i = 0; i < 4; ++i)
1744  {
1745  if(tag.year[i] != '\0') this->year += tag.year[i];
1746  else break;
1747  }
1748 
1749  // Comment
1750  for(uint32 i = 0; i < 30; ++i)
1751  {
1752  if(tag.comment[i] != '\0') this->comment += tag.comment[i];
1753  else break;
1754  }
1755 
1756  // Genre
1757  this->genre = tag.genre;
1758 
1759  return true;
1760 }
1761 
1762 boolean
1763 ID3v1Tag::
1764 write(const std::string & filename, boolean show_warnings)
1765 {
1766  FILE * fin = fopen(filename.c_str(), "r+b");
1767 
1768  if(fin == NULL)
1769  {
1770  M_THROW("ID3v1Tag::write(): could not open the file '"
1771  << filename
1772  << "'");
1773  return false;
1774  }
1775 
1776  int64 tag_pos = findID3v1Tag(fin);
1777 
1778  if(tag_pos == IO_ERROR)
1779  {
1780  M_THROW("ID3v1Tag::write(): ID3v1Tag::find() failed!"
1781  << filename
1782  << "'");
1783  return false;
1784  }
1785 
1786  // If he tag wasn't found, just go to the end of the file.
1787  else if(tag_pos == NOT_FOUND)
1788  {
1789  fseek(fin, 0, SEEK_END);
1790  }
1791 
1792  // Seek to the tag.
1793  else
1794  {
1795  #ifdef NSOUND_PLATFORM_OS_WINDOWS
1796  fseek(fin, static_cast<long>(tag_pos), SEEK_SET);
1797  #else
1798  fseek(fin, tag_pos, SEEK_SET);
1799  #endif
1800  }
1801 
1802  RawTag tag;
1803 
1804  memset(reinterpret_cast<char *>(&tag), 0, sizeof(RawTag));
1805 
1806  tag.header[0] = 'T';
1807  tag.header[1] = 'A';
1808  tag.header[2] = 'G';
1809 
1810  #define MIN(a,b) ((a < b) ? a : b)
1811 
1812  // Title
1813  for(uint32 i = 0; i < MIN(30, this->title.size()); ++i)
1814  {
1815  tag.title[i] = this->title[i];
1816  }
1817 
1818  // Artist
1819  for(uint32 i = 0; i < MIN(30, this->artist.size()); ++i)
1820  {
1821  tag.artist[i] = this->artist[i];
1822  }
1823 
1824  // Album
1825  for(uint32 i = 0; i < MIN(30, this->album.size()); ++i)
1826  {
1827  tag.album[i] = this->album[i];
1828  }
1829 
1830  // Year
1831  for(uint32 i = 0; i < MIN(4, this->year.size()); ++i)
1832  {
1833  tag.year[i] = this->year[i];
1834  }
1835 
1836  // Comment
1837  for(uint32 i = 0; i < MIN(30, this->comment.size()); ++i)
1838  {
1839  tag.comment[i] = this->comment[i];
1840  }
1841 
1842  // Genre
1843  tag.genre = this->genre;
1844 
1845  // Write the tag.
1846  if(sizeof(RawTag) != fwrite(tag.header, 1, sizeof(RawTag), fin))
1847  {
1848  fclose(fin);
1849  M_THROW("ID3v1Tag::write(): failed to write the ID3v1Tag!");
1850  return false;
1851  }
1852 
1853  fclose(fin);
1854  return true;
1855 }
1856 
1857 //-----------------------------------------------------------------------------
1858 std::ostream &
1859 Nsound::
1860 operator<<(std::ostream & out, const ID3v1Tag & rhs)
1861 {
1862  out << "header : TAG" << endl
1863  << "title : " << rhs.title << endl
1864  << "artist : " << rhs.artist << endl
1865  << "album : " << rhs.album << endl
1866  << "year : " << rhs.year << endl
1867  << "comment : " << rhs.comment << endl
1868  << "genre : " << rhs.genre;
1869 
1870  return out;
1871 }
#define NOT_FOUND
Definition: Wavefile.cc:1550
static boolean read(const std::string &fileName, AudioStream &astream)
Definition: Wavefile.cc:920
unsigned int uint32
Definition: Nsound.h:153
static const raw_float64 SIGNED_48_BIT_
Definition: Wavefile.h:134
#define IO_ERROR
Definition: Wavefile.cc:1551
static int64 readInt(FILE *fd, uint32 n_bytes)
Definition: Wavefile.cc:246
static const raw_float64 SIGNED_24_BIT_
Definition: Wavefile.h:136
char year[4]
Definition: Wavefile.cc:1524
#define M_ASSERT_VALUE(a, op, value)
Definition: Macros.h:76
static const uint32 RIFF_
Definition: Wavefile.h:126
std::ostream & operator<<(std::ostream &out, const Buffer &rhs_buffer)
Definition: Buffer.cc:1338
static boolean readHeader(const std::string &filename, std::string &info)
Reads the basic header information and sets the info string.
Definition: Wavefile.cc:934
char title[30]
Definition: Wavefile.cc:1521
#define MIN(a, b)
unsigned char uint8
Definition: Nsound.h:151
char genre
Definition: Wavefile.cc:1526
std::string title
Definition: Wavefile.h:268
static void writeFloat64(FILE *output, float64 value)
Definition: Wavefile.cc:382
float64 getSampleRate() const
Returns the sample rate of the stream.
Definition: AudioStream.h:217
char comment[30]
Definition: Wavefile.cc:1525
#define WARNING_HEADER
Definition: Nsound.h:186
static int64 swapBytesInt48(const uint64 &i)
Definition: Wavefile.cc:182
uint32 getLength() const
Returns the number of samples of audio data in the stream.
Definition: AudioStream.cc:197
#define M_CHECK_PTR(ptr)
Definition: Macros.h:64
static const raw_float64 SIGNED_16_BIT_
Definition: Wavefile.h:137
static const uint16 WAVE_FORMAT_PCM_
Definition: Wavefile.h:129
std::vector< Buffer * > BufferPointerVector
Definition: Buffer.h:2040
double float64
Definition: Nsound.h:146
char album[30]
Definition: Wavefile.cc:1523
static uint16 default_wave_format_
Definition: Wavefile.h:236
static const raw_float64 SIGNED_32_BIT_
Definition: Wavefile.h:135
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
static boolean write(const std::string &fileName, const AudioStream &as, uint32 bits_per_sample=16)
Definition: Wavefile.cc:952
static uint32 default_sample_size_
Definition: Wavefile.h:235
void setNChannels(uint32 channels)
Definition: AudioStream.cc:781
static const uint32 PEAK_
Definition: Wavefile.h:125
char header[3]
Definition: Wavefile.cc:1520
static std::string decodeFormatTag(const uint16 format_tag)
Definition: Wavefile.cc:1309
uint32 getNChannels(void) const
Returns the number of audio channels in the stream.
Definition: AudioStream.h:212
void operator>>(const AudioStream &lhs, AudioPlayback &rhs)
boolean write(const std::string &filename, boolean show_warnings=true)
Returns true if it successfully wrote the tag to the end of the file, false otherwise.
Definition: Wavefile.cc:1764
static float64 readFloat64(FILE *fd)
Definition: Wavefile.cc:325
std::vector< Buffer > BufferVector
Definition: Buffer.h:2039
static const uint32 FACT_
Definition: Wavefile.h:123
static void writeInt(FILE *output, uint32 n_bytes, int64 value)
Definition: Wavefile.cc:346
#define LM_UNUSED
Definition: Wavefile.cc:238
static int64 swapBytesInt64(const uint64 &i)
Endian Conversion.
Definition: Wavefile.cc:157
static void setDefaults(const float64 &sample_rate=44100.0, const float64 &sample_bits=16.0, const boolean &use_ieee_floats=false)
Definition: Wavefile.cc:117
static int32 swapBytesInt32(const uint32 i)
Definition: Wavefile.cc:206
unsigned long long uint64
Definition: Nsound.h:154
static void writeFloat32(FILE *output, float32 value)
Definition: Wavefile.cc:364
#define M_THROW(message)
Definition: Macros.h:108
static uint32 getDefaultSampleRate()
Definition: Wavefile.h:153
static void setIEEEFloat(boolean flag)
Definition: Wavefile.cc:98
static int32 swapBytesInt16(const uint32 i)
Definition: Wavefile.cc:225
std::string artist
Definition: Wavefile.h:269
static const raw_float64 SIGNED_8_BIT_
Definition: Wavefile.h:138
static const raw_float64 SIGNED_64_BIT_
Definition: Wavefile.h:133
A Buffer for storing audio samples.
Definition: Buffer.h:60
static const uint32 DATA_
Definition: Wavefile.h:122
struct RawTag RawTag
signed int int32
Definition: Nsound.h:142
static uint32 default_sample_rate_
Definition: Wavefile.h:234
double raw_float64
Definition: Nsound.h:159
int64 findID3v1Tag(FILE *fin)
Definition: Wavefile.cc:1554
ID3v1Tag(const std::string &filename="", boolean show_warnings=true)
Definition: Wavefile.cc:1532
float float32
Definition: Nsound.h:145
static void setDefaultSampleRate(const int32 rate)
Definition: Wavefile.cc:70
static void setDefaultSampleSize(uint32 size)
Definition: Wavefile.cc:79
boolean read(const std::string &filename, boolean show_warnings=true)
Returns true if it found the tag, false otherwise.
Definition: Wavefile.cc:1663
std::string comment
Definition: Wavefile.h:272
static uint32 getDefaultSampleSize()
Definition: Wavefile.h:157
static const uint16 WAVE_FORMAT_IEEE_FLOAT_
Definition: Wavefile.h:130
signed long long int64
Definition: Nsound.h:143
static const uint32 FMT_
Definition: Wavefile.h:124
void setSampleRate(uint32 sample_rate)
Definition: AudioStream.h:483
unsigned short uint16
Definition: Nsound.h:152
std::string year
Definition: Wavefile.h:271
std::string album
Definition: Wavefile.h:270
char artist[30]
Definition: Wavefile.cc:1522
static float32 readFloat32(FILE *fd)
Definition: Wavefile.cc:305
static const uint32 WAVE_
Definition: Wavefile.h:127
static int32 swapBytesInt24(const uint32 i)
Definition: Wavefile.cc:216