1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #include "audio/wave.h"
28 #include <libraries/iffparse.h>
29 #include <proto/exec.h>
30 #include <proto/dos.h>
36 #define ZERO MKBADDR(NULL)
51 #define ID_RIFF MAKE_ID('R','I','F','F')
52 #define ID_WAVE MAKE_ID('W','A','V','E')
53 #define ID_fmt MAKE_ID('f','m','t',' ')
54 #define ID_data MAKE_ID('d','a','t','a')
66 #define WAVE_FORMAT_PCM 0x0001
70 BOOL
WAVE_header(CONST_APTR p
) {
71 const riff_header_t
*header
= p
;
72 return rbe32(&header
->id
) == ID_RIFF
&& rbe32(&header
->type
) == ID_WAVE
;
75 static void WAVE_close(WAVE_STREAM
*stream
);
76 static LONG
WAVE_read(WAVE_STREAM
*stream
, APTR buffer
, ULONG offset
, ULONG length
);
78 WAVE_STREAM
*WAVE_open(CONST_STRPTR filename
) {
80 WAVE_STREAM
*stream
= NULL
;
88 file
= Open(filename
, MODE_OLDFILE
);
93 stream
= AllocVec(sizeof(*stream
), MEMF_CLEAR
);
95 SetIoErr(ERROR_NO_FREE_STORE
);
99 stream
->close
= WAVE_close
;
100 stream
->read
= WAVE_read
;
103 if (FRead(file
, &header
, 1, sizeof(header
)) != sizeof(header
)) {
106 if (rbe32(&header
.id
) != ID_RIFF
|| rbe32(&header
.type
) != ID_WAVE
) {
107 SetIoErr(ERROR_OBJECT_WRONG_TYPE
);
112 if (FRead(file
, &chunk
, 1, sizeof(chunk
)) != sizeof(chunk
)) {
115 wbe32(&chunk
.id
, chunk
.id
);
116 wle32(&chunk
.size
, chunk
.size
);
119 if (chunk
.size
!= 16 && chunk
.size
!= 18) {
120 SetIoErr(ERROR_OBJECT_WRONG_TYPE
);
123 if (FRead(file
, &fmt
, 1, chunk
.size
) != chunk
.size
) {
126 if (rle16(&fmt
.format
) != WAVE_FORMAT_PCM
||
127 rle16(&fmt
.channels
) != 2 ||
128 rle32(&fmt
.frequency
) != 44100 ||
129 rle16(&fmt
.bitspersample
) != 16)
131 SetIoErr(ERROR_OBJECT_WRONG_TYPE
);
136 stream
->offset
= GetFilePosition(file
);
137 stream
->length
= chunk
.size
;
138 if ((LONG
)stream
->offset
== -1 && IoErr()) {
144 if (!ChangeFilePosition(file
, (chunk
.size
+1)&~1, OFFSET_CURRENT
)) {
158 static void WAVE_close(WAVE_STREAM
*stream
) {
165 static LONG
WAVE_read(WAVE_STREAM
*stream
, APTR buffer
, ULONG offset
, ULONG length
) {
166 BPTR file
= stream
->file
;
169 if (offset
>= stream
->length
) {
170 memset(buffer
, 0, length
);
173 if (!ChangeFilePosition(file
, stream
->offset
+ offset
, OFFSET_BEGINNING
)) {
176 if ((offset
+ length
) > stream
->length
) {
177 read_length
= stream
->length
;
179 read_length
= length
;
181 bytes_read
= FRead(file
, buffer
, 1, read_length
);
182 if (bytes_read
< 0) {
185 memset((uint8
*)buffer
+ bytes_read
, 0, length
- bytes_read
);