1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   MultiFormatReader.cpp
6 
7   Philipp Sibler
8 
9 ******************************************************************//**
10 
11 \class MultiFormatReader
12 \brief MultiFormatReader reads raw audio files in different formats and
13 machine endianness representations.
14 
15 *//*******************************************************************/
16 
17 #include "MultiFormatReader.h"
18 
19 #include <exception>
20 #include <stdexcept>
21 #include <cstring>
22 #include <stdint.h>
23 #include <cstdio>
24 
25 #include <wx/defs.h>
26 
MachineEndianness()27 MachineEndianness::MachineEndianness()
28 {
29    if (wxBYTE_ORDER == wxLITTLE_ENDIAN)
30    {
31       mFlag = MachineEndianness::Little;
32    }
33    else
34    {
35       mFlag = MachineEndianness::Big;
36    }
37 }
38 
39 
MultiFormatReader(const char * filename)40 MultiFormatReader::MultiFormatReader(const char* filename)
41    : mpFid(NULL)
42 {
43    mpFid = fopen(filename, "rb");
44 
45    if (mpFid == NULL)
46    {
47       throw std::runtime_error("Error opening file");
48    }
49 }
50 
~MultiFormatReader()51 MultiFormatReader::~MultiFormatReader()
52 {
53    if (mpFid != NULL)
54    {
55       fclose(mpFid);
56    }
57 }
58 
Reset()59 void MultiFormatReader::Reset()
60 {
61    if (mpFid != NULL)
62    {
63       rewind(mpFid);
64    }
65 }
66 
ReadSamples(void * buffer,size_t len,MultiFormatReader::FormatT format,MachineEndianness::EndiannessT end)67 size_t MultiFormatReader::ReadSamples(void* buffer, size_t len,
68                     MultiFormatReader::FormatT format,
69                     MachineEndianness::EndiannessT end)
70 {
71    return ReadSamples(buffer, len, 1, format, end);
72 }
73 
74 
ReadSamples(void * buffer,size_t len,size_t stride,MultiFormatReader::FormatT format,MachineEndianness::EndiannessT end)75 size_t MultiFormatReader::ReadSamples(void* buffer, size_t len, size_t stride,
76                     MultiFormatReader::FormatT format,
77                     MachineEndianness::EndiannessT end)
78 {
79    bool swapflag = (mEnd.Which() != end);
80    size_t actRead=0;
81 
82    switch(format)
83    {
84       case Int8:
85       case Uint8:
86          actRead = Read(buffer, 1, len, stride);
87          break;
88       case Int16:
89       case Uint16:
90          actRead = Read(buffer, 2, len, stride);
91          if(swapflag) SwapBytes(buffer, 2, len);
92          break;
93       case Int32:
94       case Uint32:
95       case Float:
96          actRead = Read(buffer, 4, len, stride);
97          if(swapflag) SwapBytes(buffer, 4, len);
98          break;
99       case Double:
100          actRead = Read(buffer, 8, len, stride);
101          if(swapflag) SwapBytes(buffer, 8, len);
102          break;
103       default:
104          break;
105    }
106 
107    return actRead;
108 }
109 
Read(void * buffer,size_t size,size_t len,size_t stride)110 size_t MultiFormatReader::Read(void* buffer, size_t size, size_t len, size_t stride)
111 {
112    size_t actRead = 0;
113    uint8_t* pWork = (uint8_t*) buffer;
114 
115    if (stride > 1)
116    {
117       // There are gaps between consecutive samples,
118       // so do a scattered read
119       for (size_t n = 0; n < len; n++)
120       {
121          actRead += fread(&(pWork[n*size]), size, 1, mpFid);
122          // FIXME: TRAP_ERR fseek return in MultiFormatReader unchecked.
123          fseek(mpFid, (stride - 1) * size, SEEK_CUR);
124       }
125    }
126    else
127    {
128       // Just do a linear read
129       actRead = fread(buffer, size, len, mpFid);
130    }
131 
132    return actRead;
133 }
134 
135 
SwapBytes(void * buffer,size_t size,size_t len)136 void MultiFormatReader::SwapBytes(void* buffer, size_t size, size_t len)
137 {
138    uint8_t* pResBuffer = (uint8_t*) buffer;
139    uint8_t* pCurBuffer;
140 
141    if (size > 8)
142    {
143       throw std::runtime_error("SwapBytes Exception: Format width exceeding 8 bytes.");
144    }
145 
146    for (size_t i = 0; i < len; i++)
147    {
148       pCurBuffer = &(pResBuffer[i*size]);
149       memcpy(mSwapBuffer, &(pCurBuffer[0]), size);
150 
151       for (size_t n = 0; n < size; n++)
152       {
153          pCurBuffer[n] = mSwapBuffer[size - n - 1];
154       }
155    }
156 }
157 
158