1/*
2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24// AIFFSupport.c created by CJS on Wed 10-May-2000
25
26#ifndef __AIFF_SUPPORT_H__
27#include "AIFFSupport.h"
28#endif
29
30#ifndef __APPLE_CDDA_FS_DEBUG_H__
31#include "AppleCDDAFileSystemDebug.h"
32#endif
33
34#ifndef __APPLE_CDDA_FS_VNODE_OPS_H__
35#include "AppleCDDAFileSystemVNodeOps.h"
36#endif
37
38
39// System Includes
40#include <sys/systm.h>
41#include <libkern/OSByteOrder.h>
42
43
44#if defined(__LITTLE_ENDIAN__)
45
46// Conversion Routines
47static void
48SwapContainerChunk ( ContainerChunk * chunk );
49
50static void
51SwapFormatVersionChunk ( FormatVersionChunk * chunk );
52
53static void
54SwapExtCommonChunk ( ExtCommonChunk * chunk );
55
56static void
57SwapSoundDataChunk ( SoundDataChunk * chunk );
58
59static void
60SwapCDAIFFHeader ( CDAIFFHeader * header );
61
62static void
63SwapFloat80	( Float80 * value );
64
65
66//-----------------------------------------------------------------------------
67// 	SwapContainerChunk	-	This converts a little endian representation
68//									of a ContainerChunk into a big endian
69//									representation
70//-----------------------------------------------------------------------------
71
72static void
73SwapContainerChunk ( ContainerChunk * chunk )
74{
75
76	chunk->ckID 	= OSSwapInt32 ( chunk->ckID );
77	chunk->ckSize	= OSSwapInt32 ( chunk->ckSize );
78	chunk->formType	= OSSwapInt32 ( chunk->formType );
79
80}
81
82
83//-----------------------------------------------------------------------------
84// 	SwapContainerChunk	-	This converts a little endian representation
85//										of a FormatVersionChunk into a big endian
86//										representation
87//-----------------------------------------------------------------------------
88
89static void
90SwapFormatVersionChunk ( FormatVersionChunk * chunk )
91{
92
93	chunk->ckID 		= OSSwapInt32 ( chunk->ckID );
94	chunk->ckSize		= OSSwapInt32 ( chunk->ckSize );
95	chunk->timeStamp	= OSSwapInt32 ( chunk->timeStamp );
96
97}
98
99
100//-----------------------------------------------------------------------------
101// 	SwapExtCommonChunk	-	This converts a little endian representation
102//									of an ExtCommonChunk into a big endian
103//									representation
104//-----------------------------------------------------------------------------
105
106static void
107SwapExtCommonChunk ( ExtCommonChunk * chunk )
108{
109
110	SwapFloat80 ( &chunk->sampleRate );
111
112	chunk->ckID				= OSSwapInt32 ( chunk->ckID );
113	chunk->ckSize			= OSSwapInt32 ( chunk->ckSize );
114	chunk->numChannels		= OSSwapInt16 ( chunk->numChannels );
115	chunk->numSampleFrames	= OSSwapInt32 ( chunk->numSampleFrames );
116	chunk->sampleSize		= OSSwapInt16 ( chunk->sampleSize );
117	chunk->compressionType	= OSSwapInt32 ( chunk->compressionType );
118
119}
120
121
122//-----------------------------------------------------------------------------
123// 	SwapSoundDataChunk	-	This converts a little endian representation
124//									of a SoundDataChunk into a big endian
125//									representation
126//-----------------------------------------------------------------------------
127
128static void
129SwapSoundDataChunk ( SoundDataChunk * chunk )
130{
131
132	chunk->ckID 		= OSSwapInt32 ( chunk->ckID );
133	chunk->ckSize 		= OSSwapInt32 ( chunk->ckSize );
134	chunk->offset		= OSSwapInt32 ( chunk->offset );
135	chunk->blockSize	= OSSwapInt32 ( chunk->blockSize );
136
137}
138
139
140//-----------------------------------------------------------------------------
141// 	SwapCDAIFFHeader	-	This converts a little endian representation
142//								of a CDAIFFHeader into a big endian
143//								representation
144//-----------------------------------------------------------------------------
145
146static void
147SwapCDAIFFHeader ( CDAIFFHeader * header )
148{
149
150	SwapContainerChunk ( &header->containerChunk );
151	SwapFormatVersionChunk ( &header->formatVersionChunk );
152	SwapExtCommonChunk ( &header->commonChunk );
153	SwapSoundDataChunk ( &header->soundDataChunk );
154
155}
156
157
158//-----------------------------------------------------------------------------
159// 	SwapFloat80	-	This converts a little endian representation
160//							of a Float80 into a big endian representation
161//-----------------------------------------------------------------------------
162
163static void
164SwapFloat80	( Float80 * data )
165{
166
167	data->exp 		= OSSwapInt16 ( data->exp );
168	data->man[0]	= OSSwapInt16 ( data->man[0] );
169	data->man[1]	= OSSwapInt16 ( data->man[1] );
170	data->man[2]	= OSSwapInt16 ( data->man[2] );
171	data->man[3]	= OSSwapInt16 ( data->man[3] );
172
173}
174
175
176#endif /* defined(__LITTLE_ENDIAN__) */
177
178
179//-----------------------------------------------------------------------------
180// 	BuildCDAIFFHeader	-	This routine builds a CDAIFFHeader and explicitly
181//							makes it Big Endian (as defined by AIFF standard)
182//-----------------------------------------------------------------------------
183
184void
185BuildCDAIFFHeader ( CDAIFFHeader * header, uint32_t fileSize )
186{
187
188	ExtCommonChunk *		commonChunkPtr 			= NULL;
189	SoundDataChunk *		soundDataChunkPtr		= NULL;
190	ContainerChunk *		containerChunkPtr		= NULL;
191	FormatVersionChunk *	formatVersionChunkPtr	= NULL;
192	uint32_t				dataSize				= fileSize - kPhysicalMediaBlockSize;
193
194	// Get the address of each sub-structure to make this easier to read
195	commonChunkPtr			= &header->commonChunk;
196	soundDataChunkPtr		= &header->soundDataChunk;
197	containerChunkPtr		= &header->containerChunk;
198	formatVersionChunkPtr	= &header->formatVersionChunk;
199
200	// Setup the version chunk
201	formatVersionChunkPtr->ckID			= kFormatVersionID;
202	formatVersionChunkPtr->ckSize		= ( uint32_t )( sizeof ( FormatVersionChunk ) - sizeof ( ChunkHeader ) );
203	formatVersionChunkPtr->timeStamp	= kAIFCVersion1;
204
205	// Setup the common chunk
206	commonChunkPtr->ckID 				= kCommonID;
207	commonChunkPtr->ckSize 				= ( uint32_t )( sizeof ( ExtCommonChunk ) - sizeof ( ChunkHeader ) );
208	commonChunkPtr->numChannels 		= kStereo;			// 2 channels
209	commonChunkPtr->numSampleFrames 	= dataSize / 4; 	// 4 = ( k16BitsPerSample / 8 ) * kStereo
210	commonChunkPtr->sampleSize 			= k16BitsPerSample;	// Set the sample size to 16 bits
211	commonChunkPtr->sampleRate.exp 		= 0x400E;			// Set the sample rate to 44.1 KHz
212	commonChunkPtr->sampleRate.man[0] 	= 0xAC44;			// Set the sample rate to 44.1 KHz
213	commonChunkPtr->sampleRate.man[1]	= 0x0000;			// Set the sample rate to 44.1 KHz
214	commonChunkPtr->sampleRate.man[2]	= 0x0000;			// Set the sample rate to 44.1 KHz
215	commonChunkPtr->sampleRate.man[3]	= 0x0000;			// Set the sample rate to 44.1 KHz
216
217	// Data streamed off disc is in little endian format
218	commonChunkPtr->compressionType	= k16BitLittleEndianFormat;
219
220	// Setup the soundData chunk
221	soundDataChunkPtr->ckID 		= kSoundDataID;
222	soundDataChunkPtr->offset 		= ( uint32_t ) ( kPhysicalMediaBlockSize - sizeof ( CDAIFFHeader ) );
223	soundDataChunkPtr->ckSize 		= ( uint32_t ) ( ( sizeof ( SoundDataChunk ) - sizeof ( ChunkHeader ) ) +
224									  dataSize + soundDataChunkPtr->offset );
225	soundDataChunkPtr->blockSize 	= 0;
226
227	// Setup the container chunk
228	containerChunkPtr->ckID 	= kFormID;
229	containerChunkPtr->ckSize 	= ( uint32_t )
230								  ( ( sizeof ( ContainerChunk ) - sizeof ( ChunkHeader ) ) +		// size of container chunk variables
231					   			    ( formatVersionChunkPtr->ckSize + sizeof ( ChunkHeader ) ) + 	// size of common chunk
232					   			    ( commonChunkPtr->ckSize + sizeof ( ChunkHeader ) ) +			// size of common chunk
233					   			    ( soundDataChunkPtr->ckSize + sizeof ( ChunkHeader ) ) );		// size of sound data chunk
234
235	// Save as uncompressed AIFF-C
236	containerChunkPtr->formType = kAIFCID;
237
238#if defined(__LITTLE_ENDIAN__)
239
240	// Convert from natural byte order to big endian byte order
241	// because AIFF Header data MUST be big endian (the audio data
242	// doesn't necessarily have to)
243	SwapCDAIFFHeader ( header );
244
245#endif /* defined(__LITTLE_ENDIAN__) */
246
247}
248
249
250//-----------------------------------------------------------------------------
251//				End				Of			File
252//-----------------------------------------------------------------------------
253