Nsound  0.9.4
Classes | Macros | Typedefs | Functions
Wavefile.cc File Reference
#include <Nsound/Nsound.h>
#include <Nsound/AudioStream.h>
#include <Nsound/Buffer.h>
#include <Nsound/Wavefile.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <sstream>
Include dependency graph for Wavefile.cc:

Go to the source code of this file.

Classes

struct  RawTag
 

Macros

#define LM_UNUSED   __attribute__((unused))
 
#define NOT_FOUND   -1
 
#define IO_ERROR   -2
 
#define MIN(a, b)   ((a < b) ? a : b)
 

Typedefs

typedef struct RawTag RawTag
 

Functions

static int64 swapBytesInt64 (const uint64 &i)
 Endian Conversion. More...
 
static int64 swapBytesInt48 (const uint64 &i)
 
static int32 swapBytesInt32 (const uint32 i)
 
static int32 swapBytesInt24 (const uint32 i)
 
static int32 swapBytesInt16 (const uint32 i)
 
static int64 readInt (FILE *fd, uint32 n_bytes)
 
static float32 readFloat32 (FILE *fd)
 
static float64 readFloat64 (FILE *fd)
 
static void writeInt (FILE *output, uint32 n_bytes, int64 value)
 
static void writeFloat32 (FILE *output, float32 value)
 
static void writeFloat64 (FILE *output, float64 value)
 
int64 findID3v1Tag (FILE *fin)
 

Macro Definition Documentation

#define LM_UNUSED   __attribute__((unused))

Definition at line 238 of file Wavefile.cc.

Referenced by readFloat32(), readFloat64(), and readInt().

#define NOT_FOUND   -1

Definition at line 1550 of file Wavefile.cc.

Referenced by findID3v1Tag(), Nsound::ID3v1Tag::read(), and Nsound::ID3v1Tag::write().

#define IO_ERROR   -2

Definition at line 1551 of file Wavefile.cc.

Referenced by findID3v1Tag(), Nsound::ID3v1Tag::read(), and Nsound::ID3v1Tag::write().

#define MIN (   a,
 
)    ((a < b) ? a : b)

Referenced by Nsound::ID3v1Tag::write().

Typedef Documentation

typedef struct RawTag RawTag

Function Documentation

static int64 swapBytesInt64 ( const uint64 i)
inlinestatic

Endian Conversion.

little endian: intel big endian: power pc, sparc

4 bytes little endian byte order: 1234 big endian byte order: 4321

3 bytes little endian byte order: 123 big endian byte order: 321

2 bytes little endian byte order: 12 big endian byte order: 21

The method below takes an int and swaps the bytes. Note that on either endian system the method will do the correct converstion. That is, a big endian value will become a little (4321 –> 1234), and a little endian becomes big (1234 –> 4321).

Definition at line 157 of file Wavefile.cc.

Referenced by readFloat64(), readInt(), writeFloat64(), and writeInt().

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 };
unsigned char uint8
Definition: Nsound.h:151
signed long long int64
Definition: Nsound.h:143
static int64 swapBytesInt48 ( const uint64 i)
inlinestatic

Definition at line 182 of file Wavefile.cc.

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 };
unsigned char uint8
Definition: Nsound.h:151
signed long long int64
Definition: Nsound.h:143
static int32 swapBytesInt32 ( const uint32  i)
inlinestatic

Definition at line 206 of file Wavefile.cc.

Referenced by readFloat32(), readFloat64(), writeFloat32(), and writeFloat64().

207 {
208  return static_cast<int32>(((i & 0xff000000) >> 24 |
209  ((i & 0x00ff0000) >> 8 |
210  ((i & 0x0000ff00) << 8 |
211  ((i & 0x000000ff) << 24)))));
212 };
signed int int32
Definition: Nsound.h:142
static int32 swapBytesInt24 ( const uint32  i)
inlinestatic

Definition at line 216 of file Wavefile.cc.

217 {
218  return static_cast<int32>(((i & 0x00ff0000) >> 16 |
219  ((i & 0x0000ff00) |
220  ((i & 0x000000ff) << 16))));
221 };
signed int int32
Definition: Nsound.h:142
static int32 swapBytesInt16 ( const uint32  i)
inlinestatic

Definition at line 225 of file Wavefile.cc.

226 {
227  return static_cast<int32>(((i & 0x0000ff00) >> 8 |
228  ((i & 0x000000ff) << 8)));
229 };
signed int int32
Definition: Nsound.h:142
static int64 readInt ( FILE *  fd,
uint32  n_bytes 
)
inlinestatic

This method reads data from the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 246 of file Wavefile.cc.

References LM_UNUSED, and swapBytesInt64().

Referenced by findID3v1Tag().

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 }
#define LM_UNUSED
Definition: Wavefile.cc:238
static int64 swapBytesInt64(const uint64 &i)
Endian Conversion.
Definition: Wavefile.cc:157
signed long long int64
Definition: Nsound.h:143
static float32 readFloat32 ( FILE *  fd)
inlinestatic

This method reads data from the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 305 of file Wavefile.cc.

References LM_UNUSED, and swapBytesInt32().

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 }
#define LM_UNUSED
Definition: Wavefile.cc:238
static int32 swapBytesInt32(const uint32 i)
Definition: Wavefile.cc:206
signed int int32
Definition: Nsound.h:142
float float32
Definition: Nsound.h:145
static float64 readFloat64 ( FILE *  fd)
inlinestatic

This method reads data from the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 325 of file Wavefile.cc.

References LM_UNUSED, swapBytesInt32(), and swapBytesInt64().

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 }
double float64
Definition: Nsound.h:146
#define LM_UNUSED
Definition: Wavefile.cc:238
static int64 swapBytesInt64(const uint64 &i)
Endian Conversion.
Definition: Wavefile.cc:157
static int32 swapBytesInt32(const uint32 i)
Definition: Wavefile.cc:206
signed long long int64
Definition: Nsound.h:143
static void writeInt ( FILE *  output,
uint32  n_bytes,
int64  value 
)
inlinestatic

This method writes data to the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 346 of file Wavefile.cc.

References swapBytesInt64().

Referenced by Nsound::Wavefile::write().

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 }
static int64 swapBytesInt64(const uint64 &i)
Endian Conversion.
Definition: Wavefile.cc:157
static void writeFloat32 ( FILE *  output,
float32  value 
)
inlinestatic

This method writes data to the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 364 of file Wavefile.cc.

References swapBytesInt32().

Referenced by Nsound::Wavefile::write().

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 }
unsigned int uint32
Definition: Nsound.h:153
static int32 swapBytesInt32(const uint32 i)
Definition: Wavefile.cc:206
float float32
Definition: Nsound.h:145
static void writeFloat64 ( FILE *  output,
float64  value 
)
inlinestatic

This method writes data to the file and does the proper byte conversion based on the endianess of the platform.

Definition at line 382 of file Wavefile.cc.

References swapBytesInt32(), and swapBytesInt64().

Referenced by Nsound::Wavefile::write().

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 }
double float64
Definition: Nsound.h:146
static int64 swapBytesInt64(const uint64 &i)
Endian Conversion.
Definition: Wavefile.cc:157
static int32 swapBytesInt32(const uint32 i)
Definition: Wavefile.cc:206
unsigned long long uint64
Definition: Nsound.h:154
int64 findID3v1Tag ( FILE *  fin)

Definition at line 1554 of file Wavefile.cc.

References Nsound::Wavefile::DATA_, IO_ERROR, M_CHECK_PTR, M_THROW, NOT_FOUND, readInt(), Nsound::Wavefile::RIFF_, and Nsound::Wavefile::WAVE_.

Referenced by Nsound::ID3v1Tag::read(), and Nsound::ID3v1Tag::write().

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 }
#define NOT_FOUND
Definition: Wavefile.cc:1550
unsigned int uint32
Definition: Nsound.h:153
#define IO_ERROR
Definition: Wavefile.cc:1551
static int64 readInt(FILE *fd, uint32 n_bytes)
Definition: Wavefile.cc:246
#define M_CHECK_PTR(ptr)
Definition: Macros.h:64
#define M_THROW(message)
Definition: Macros.h:108