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