4 #include <exec/execbase.h>
5 #include <libraries/ahi_sub.h>
6 #include <libraries/asl.h>
7 #include <proto/exec.h>
9 #include <proto/intuition.h>
13 #include "DriverData.h"
14 #include "FileFormats.h"
17 #define dd ((struct FilesaveData*) AudioCtrl->ahiac_DriverData)
19 #define abs(x) ((x)<0?(-x):(x))
21 void ulong2extended (ULONG in
, extended
*ex
);
23 /******************************************************************************
24 ** Endian conversion **********************************************************
25 ******************************************************************************/
27 #ifdef WORDS_BIGENDIAN
29 #define __htole_short(x) \
30 ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
32 #define __htole_long(x) \
33 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
34 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
37 htole_short( unsigned short x
)
39 return (unsigned short) __htole_short( x
);
43 htole_long( unsigned long x
)
45 return __htole_long( x
);
48 #define __htobe_short(x) (x)
49 #define __htobe_long(x) (x)
50 #define htobe_short(x) (x)
51 #define htobe_long(x) (x)
55 #define __htole_short(x) (x)
56 #define __htole_long(x) (x)
57 #define htole_short(x) (x)
58 #define htole_long(x) (x)
60 #define __htobe_short(x) \
61 ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
63 #define __htobe_long(x) \
64 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
65 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
68 htobe_short( unsigned short x
)
70 return (unsigned short) __htobe_short( x
);
74 htobe_long( unsigned long x
)
76 return __htobe_long( x
);
82 /******************************************************************************
83 ** The slave process **********************************************************
84 ******************************************************************************/
87 #if defined( __MORPHOS__ )
89 /* For f*cks sake!!! Don't use SysBase in memcpy()! */
92 memcpy(void *dst
, const void *src
, size_t len
)
103 static void PlaySlave( struct ExecBase
* SysBase
);
105 #if defined( __AROS__ )
107 #include <aros/asmcall.h>
109 AROS_UFH3(void, PlaySlaveEntry
,
110 AROS_UFHA(STRPTR
, argPtr
, A0
),
111 AROS_UFHA(ULONG
, argSize
, D0
),
112 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
115 PlaySlave( SysBase
);
121 void PlaySlaveEntry(void)
123 struct ExecBase
* SysBase
= *((struct ExecBase
**) 4);
125 PlaySlave( SysBase
);
130 static void PlaySlave( struct ExecBase
* SysBase
)
132 struct AHIAudioCtrlDrv
* AudioCtrl
;
133 struct DriverBase
* AHIsubBase
;
134 struct FilesaveBase
* FilesaveBase
;
136 struct EIGHTSVXheader EIGHTSVXheader
= // All 0s will be filled later.
138 __htobe_long(ID_FORM
), 0, __htobe_long(ID_8SVX
),
139 __htobe_long(ID_VHDR
), __htobe_long(sizeof(Voice8Header
)),
147 __htobe_long(0x10000)
149 __htobe_long(ID_BODY
), 0
152 struct AIFFheader AIFFheader
= // All 0s will be filled later.
154 __htobe_long(ID_FORM
), 0, __htobe_long(ID_AIFF
),
155 __htobe_long(ID_COMM
), __htobe_long(sizeof(CommonChunk
)),
164 __htobe_long(ID_SSND
), 0,
171 struct AIFCheader AIFCheader
= // All 0s will be filled later.
173 __htobe_long(ID_FORM
), 0, __htobe_long(ID_AIFC
),
174 __htobe_long(ID_FVER
), __htobe_long(sizeof(FormatVersionHeader
)),
176 __htobe_long(AIFCVersion1
)
178 __htobe_long(ID_COMM
), __htobe_long(sizeof(ExtCommonChunk
)),
186 __htobe_long(NO_COMPRESSION
),
187 { sizeof("not compressed") - 1,
188 'n','o','t',' ','c','o','m','p','r','e','s','s','e','d' }
190 __htobe_long(ID_SSND
), 0,
197 struct STUDIO16FILE S16header
= // All 0s will be filled later.
199 __htobe_long(S16FID
),
201 __htobe_long(S16FINIT
),
202 __htobe_short(S16_VOL_0
),
218 struct WAVEheader WAVEheader
= // All 0s will be filled later.
220 __htobe_long(ID_RIFF
), 0, __htobe_long(ID_WAVE
),
221 __htobe_long(ID_fmt
), __htole_long( sizeof(FormatChunk
) ),
223 __htole_short( WAVE_PCM
),
230 __htobe_long(ID_data
), 0
233 BPTR lock
= 0,cd
= 0,file
= 0, file2
= 0;
235 ULONG signals
, i
, samplesAdd
=0, samples
= 0, length
= 0;
236 ULONG offset
= 0, bytesInBuffer
= 0, samplesWritten
= 0, bytesWritten
= 0;
238 /* Note that in OS4, we cannot call FindTask(NULL) here, since IExec
239 * is inside AHIsubBase! */
240 AudioCtrl
= (struct AHIAudioCtrlDrv
*) FindTask(NULL
)->tc_UserData
;
241 AHIsubBase
= (struct DriverBase
*) dd
->fs_AHIsubBase
;
242 FilesaveBase
= (struct FilesaveBase
*) AHIsubBase
;
244 // We cannot handle stereo 8SVXs!
245 if( (dd
->fs_Format
== FORMAT_8SVX
) &&
246 (AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
) )
251 if((dd
->fs_SlaveSignal
= AllocSignal(-1)) == -1)
256 if(!(lock
= Lock(dd
->fs_FileReq
->fr_Drawer
, ACCESS_READ
)))
261 cd
= CurrentDir(lock
);
263 switch(dd
->fs_Format
)
266 if(!(file
= Open(dd
->fs_FileReq
->fr_File
, MODE_NEWFILE
))) goto quit
;
267 Write(file
, &EIGHTSVXheader
, sizeof EIGHTSVXheader
);
271 if(!(file
= Open(dd
->fs_FileReq
->fr_File
, MODE_NEWFILE
))) goto quit
;
272 Write(file
, &AIFFheader
, sizeof AIFFheader
);
276 if(!(file
= Open(dd
->fs_FileReq
->fr_File
, MODE_NEWFILE
))) goto quit
;
277 Write(file
, &AIFCheader
, sizeof AIFCheader
);
281 if (AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
286 strncpy (filename
, dd
->fs_FileReq
->fr_File
, sizeof(filename
) - 3);
287 len
= strlen(filename
);
289 if(len
>= 2 && filename
[len
- 2] == '_'
290 && (filename
[len
- 1] == 'L' || filename
[len
- 1] == 'R'))
292 filename
[len
- 1] = 'L';
296 strcat (filename
, "_L");
299 if(!(file
= Open(filename
, MODE_NEWFILE
))) goto quit
;
301 filename
[strlen(filename
) - 1] = 'R';
302 if(!(file2
= Open(filename
, MODE_NEWFILE
))) goto quit
;
304 Write(file
, &S16header
, sizeof S16header
);
305 Write(file2
, &S16header
, sizeof S16header
);
309 if(!(file
= Open(dd
->fs_FileReq
->fr_File
, MODE_NEWFILE
))) goto quit
;
310 Write(file
, &S16header
, sizeof S16header
);
315 if(!(file
= Open(dd
->fs_FileReq
->fr_File
, MODE_NEWFILE
))) goto quit
;
316 Write(file
, &WAVEheader
, sizeof WAVEheader
);
320 // Everything set up. Tell Master we're alive and healthy.
321 Signal((struct Task
*)dd
->fs_MasterTask
,1L<<dd
->fs_MasterSignal
);
325 signals
= SetSignal(0L,0L);
326 if(signals
& (SIGBREAKF_CTRL_C
| 1L<<dd
->fs_SlaveSignal
))
331 CallHookPkt(AudioCtrl
->ahiac_PlayerFunc
, AudioCtrl
, NULL
);
332 CallHookPkt(AudioCtrl
->ahiac_MixerFunc
, AudioCtrl
, dd
->fs_MixBuffer
);
334 samplesAdd
= AudioCtrl
->ahiac_BuffSamples
;
335 samples
= samplesAdd
;
337 if(AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
)
342 // Search for loudest part in sample
343 if(AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
345 for(i
= 0; i
< samples
; i
++)
346 if(abs(((LONG
*)dd
->fs_MixBuffer
)[i
]) > maxVolume
)
347 maxVolume
= abs(((LONG
*)dd
->fs_MixBuffer
)[i
]);
351 for(i
= 0; i
< samples
; i
++)
352 if(abs(((WORD
*)dd
->fs_MixBuffer
)[i
]) > maxVolume
)
353 maxVolume
= abs(((WORD
*)dd
->fs_MixBuffer
)[i
]);
356 if((AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
) && dd
->fs_Format
== FORMAT_S16
)
358 samples
>>= 1; // Two buffers instead
361 if(offset
+samples
>= dd
->fs_SaveBufferSize
)
363 if((ULONG
) Write(file
, dd
->fs_SaveBuffer
, bytesInBuffer
) != bytesInBuffer
)
368 if((ULONG
) Write(file2
, dd
->fs_SaveBuffer2
, bytesInBuffer
) != bytesInBuffer
)
377 switch(dd
->fs_Format
)
380 if(AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
382 BYTE
*dest
= &((BYTE
*) dd
->fs_SaveBuffer
)[offset
];
383 LONG
*source
= dd
->fs_MixBuffer
;
385 for(i
= 0; i
< samples
; i
++)
386 *dest
++ = *source
++ >> 24;
390 BYTE
*dest
= &((BYTE
*) dd
->fs_SaveBuffer
)[offset
];
391 WORD
*source
= dd
->fs_MixBuffer
;
393 for(i
= 0; i
< samples
; i
++)
394 *dest
++ = *source
++ >> 8;
401 if(AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
403 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
404 LONG
*source
= dd
->fs_MixBuffer
;
406 for(i
= 0; i
< samples
; i
++)
408 *dest
++ = htobe_short( *source
++ >> 16 );
413 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
414 WORD
*source
= dd
->fs_MixBuffer
;
416 for(i
= 0; i
< samples
; i
++)
418 *dest
++ = htobe_short( *source
++ );
425 switch(AudioCtrl
->ahiac_Flags
& (AHIACF_HIFI
| AHIACF_STEREO
))
429 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
430 WORD
*source
= dd
->fs_MixBuffer
;
432 for(i
= 0; i
< samples
; i
++)
434 *dest
++ = htobe_short( *source
++ );
442 WORD
*dest1
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
443 WORD
*dest2
= &((WORD
*) dd
->fs_SaveBuffer2
)[offset
];
444 WORD
*source
= dd
->fs_MixBuffer
;
446 for(i
= 0; i
< samples
; i
++)
448 *dest1
++ = htobe_short( *source
++ );
449 *dest2
++ = htobe_short( *source
++ );
457 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
458 LONG
*source
= dd
->fs_MixBuffer
;
460 for(i
= 0; i
< samples
; i
++)
462 *dest
++ = htobe_short( *source
++ >> 16 );
468 case (AHIACF_HIFI
| AHIACF_STEREO
):
470 WORD
*dest1
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
471 WORD
*dest2
= &((WORD
*) dd
->fs_SaveBuffer2
)[offset
];
472 LONG
*source
= dd
->fs_MixBuffer
;
474 for(i
= 0; i
< samples
; i
++)
476 *dest1
++ = htobe_short( *source
++ >> 16 );
477 *dest2
++ = htobe_short( *source
++ >> 16 );
488 if(AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
490 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
491 LONG
*source
= dd
->fs_MixBuffer
;
493 for(i
= 0; i
< samples
; i
++)
495 *dest
++ = htole_short( *source
++ >> 16 );
500 WORD
*dest
= &((WORD
*) dd
->fs_SaveBuffer
)[offset
];
501 WORD
*source
= dd
->fs_MixBuffer
;
503 for(i
= 0; i
< samples
; i
++)
505 *dest
++ = htole_short( *source
++ );
513 samplesWritten
+= samplesAdd
;
514 bytesWritten
+= length
;
515 bytesInBuffer
+= length
;
518 Write(file
, dd
->fs_SaveBuffer
, bytesInBuffer
);
521 Write(file2
, dd
->fs_SaveBuffer2
, bytesInBuffer
);
524 switch(dd
->fs_Format
)
527 EIGHTSVXheader
.FORMsize
= htobe_long(sizeof(EIGHTSVXheader
)-8+bytesWritten
);
528 EIGHTSVXheader
.VHDRchunk
.oneShotHiSamples
= htobe_long(samplesWritten
);
529 EIGHTSVXheader
.VHDRchunk
.samplesPerSec
= htobe_short(AudioCtrl
->ahiac_MixFreq
);
530 EIGHTSVXheader
.BODYsize
= htobe_long(bytesWritten
);
532 FPutC(file
,'\0'); // Pad to even
533 Seek(file
,0,OFFSET_BEGINNING
);
534 Write(file
,&EIGHTSVXheader
,sizeof EIGHTSVXheader
);
538 AIFFheader
.FORMsize
= htobe_long(sizeof(AIFFheader
)-8+bytesWritten
);
539 AIFFheader
.COMMchunk
.numChannels
= htobe_short((AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
? 2 : 1));
540 AIFFheader
.COMMchunk
.numSampleFrames
= htobe_long(samplesWritten
);
541 ulong2extended(AudioCtrl
->ahiac_MixFreq
,&AIFFheader
.COMMchunk
.sampleRate
);
542 AIFFheader
.SSNDsize
= htobe_long(sizeof(SampledSoundHeader
)+bytesWritten
);
543 Seek(file
,0,OFFSET_BEGINNING
);
544 Write(file
,&AIFFheader
,sizeof AIFFheader
);
548 AIFCheader
.FORMsize
= htobe_long(sizeof(AIFCheader
)-8+bytesWritten
);
549 AIFCheader
.COMMchunk
.numChannels
= htobe_short((AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
? 2 : 1));
550 AIFCheader
.COMMchunk
.numSampleFrames
= htobe_long(samplesWritten
);
551 ulong2extended(AudioCtrl
->ahiac_MixFreq
,&AIFCheader
.COMMchunk
.sampleRate
);
552 AIFCheader
.SSNDsize
= htobe_long(sizeof(SampledSoundHeader
)+bytesWritten
);
553 Seek(file
,0,OFFSET_BEGINNING
);
554 Write(file
,&AIFCheader
,sizeof AIFCheader
);
558 S16header
.S16F_RATE
= htobe_long(AudioCtrl
->ahiac_MixFreq
);
559 S16header
.S16F_SAMPLES0
=
560 S16header
.S16F_SAMPLES1
= htobe_long(samplesWritten
);
561 S16header
.S16F_SAMPLES2
= htobe_long(samplesWritten
- 1);
564 S16header
.S16F_PAN
= htobe_long(S16_PAN_MID
);
568 S16header
.S16F_PAN
= htobe_long(S16_PAN_LEFT
);
571 Seek(file
, 0, OFFSET_BEGINNING
);
572 Write(file
, &S16header
, sizeof S16header
);
575 S16header
.S16F_PAN
= htobe_long(S16_PAN_RIGHT
);
576 Seek(file2
,0,OFFSET_BEGINNING
);
577 Write(file2
, &S16header
, sizeof S16header
);
586 num_channels
= AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
? 2 : 1;
587 block_align
= num_channels
* 16 / 8;
589 WAVEheader
.FORMsize
= htole_long( sizeof(WAVEheader
)-8+bytesWritten
);
590 WAVEheader
.FORMATchunk
.numChannels
= htole_short( num_channels
);
591 WAVEheader
.FORMATchunk
.samplesPerSec
= htole_long( AudioCtrl
->ahiac_MixFreq
);
592 WAVEheader
.FORMATchunk
.avgBytesPerSec
= htole_long( AudioCtrl
->ahiac_MixFreq
* block_align
);
593 WAVEheader
.FORMATchunk
.blockAlign
= htole_short( block_align
);
594 WAVEheader
.DATAsize
= htole_long( bytesWritten
);
595 Seek(file
,0,OFFSET_BEGINNING
);
596 Write(file
,&WAVEheader
,sizeof WAVEheader
);
601 if(AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
606 Req("Rendering finished.\nTo futher improve the quality of the sample,\n"
607 "you can raise the volume to %ld%% and render again.",
627 dd
->fs_SlaveTask
= NULL
;
628 FreeSignal(dd
->fs_SlaveSignal
);
629 dd
->fs_SlaveSignal
= -1;
630 // Tell the Master we're dying
631 Signal((struct Task
*)dd
->fs_MasterTask
,1L<<dd
->fs_MasterSignal
);
632 // Multitaking will resume when we are dead.
636 ** Apple's 80-bit SANE extended has the following format:
639 +-+-------------+-+-----------------------------+
641 +-+-------------+-+-----------------------------+
644 The value v of the number is determined by these fields as follows:
645 If 0 <= e < 32767, then v = (-1)^s * 2^(e-16383) * (i.f).
646 If e == 32767 and f == 0, then v = (-1)^s * (infinity), regardless of i.
647 If e == 32767 and f != 0, then v is a NaN, regardless of i.
650 void ulong2extended (ULONG in
, extended
*ex
)
652 ex
->exponent
= 31+16383;
654 while(!(in
& 0x80000000))
659 ex
->mantissa
[0] = in
;
661 ex
->exponent
= htobe_short( ex
->exponent
);
662 ex
->mantissa
[0] = htobe_long( ex
->mantissa
[0] );
663 ex
->mantissa
[1] = htobe_long( ex
->mantissa
[1] );