1 /* $Id: aiff_write.c,v 1.8 2006/09/16 10:07:48 toad32767 Exp $ */
2 /**
3 ** 2005, 2006 by Marco Trillo
4 ** This file is part of UModPlayer, and is released by
5 ** its autors to the Public Domain.
6 ** In case it's not legally possible, its autors grant
7 ** anyone the right to use, redistribute and modify
8 ** this software for any purpose, without any conditions,
9 ** unless such conditions are required by law.
10 **
11 ** THIS FILE COMES WITHOUT ANY WARRANTY. THE AUTHORS
12 ** SHALL NOT BE LIABLE FOR ANY DAMAGE RESULTING BY THE
13 ** USE OR MISUSE OF THIS SOFTWARE.
14 **/
15
16 /*
17 * ===================================================
18 * Apple/SGI AIFF files
19 * Use LibAiff to write the files
20 * ===================================================
21 */
22
23 #include <umodplayer.h>
24 #include <file_read.h>
25 #include <text.h>
26 #include <coresound.h>
27 #include <messages.h>
28
29 #include <libaiff/libaiff.h>
30
31 EXPORT int
WriteAIFF(const char * rfile,int bitsPerSample)32 WriteAIFF(const char *rfile, int bitsPerSample)
33 {
34 AIFF_WriteRef out;
35 IFFType typ;
36 uint8_t buffer[65536];
37 int32_t *samples = (int32_t *) buffer;
38 int bytes_out;
39 int samples_read;
40 int order;
41 char *name, *annotations;
42 int i, n;
43 /* XXX -- variables used for ugly hack */
44 char *filenam;
45 int verbosity;
46
47 if (file.name == NULL) {
48 return (0);
49 }
50
51 /*
52 * We`ll tell ModPlug to deliver 32-bit audio.
53 * Then LibAiff should do the conversion to 'bitsPerSample'
54 */
55 CoreSound_BitsPerSample = 32;
56 CoreSound_InitOptions();
57
58 /*
59 * XXX -- ugly hack to get rid of LibModPlug 0.8 settings updating annoyance.
60 * XXX LibModPlug will not update 'basic' settings such as
61 * XXX sampling rate or bits-per-sample until a new module is loaded...
62 */
63 filenam = strcopyof(file.name);
64 if (filenam == NULL) {
65 error("%s", MESSAGE_NO_MEMORY);
66 exit(UM_ERR_MEMORY);
67 }
68 UFreeFile();
69 verbosity = sets.verbosity;
70 sets.verbosity = 0; /* XXX -- to avoid the call to DrawInfoTable() */
71 file.name = filenam;
72 file.malloc = TRUE;
73 ULoadFile();
74 sets.verbosity = verbosity;
75 if (file.name == NULL) {
76 return (0);
77 }
78 CoreSound_BitsPerSample = 32;
79 CoreSound_InitOptions();
80 /* end of ugly hack */
81
82 notice("Exporting audio as AIFF ('%s')\n", rfile);
83
84 /* Open the output stream */
85 out = AIFF_WriteOpen(rfile);
86 if (out == NULL)
87 return 0;
88
89 /* Set the sound options. */
90 if (AIFF_SetSoundFormat(out, sets.channels, sets.samplerate, bitsPerSample) < 1) {
91 AIFF_WriteClose(out);
92 return 0;
93 }
94 /* Write the song name */
95 name = (char *) ModPlug_GetName(file.mod);
96 memcpy(&typ, NameID, 4);
97 if (AIFF_SetAttribute(out, typ, name) < 1) {
98 AIFF_WriteClose(out);
99 return 0;
100 }
101 /* Write the module comments (annotations), if any */
102 annotations = ModPlug_GetMessage(file.mod);
103 if (annotations) {
104 n = strlen(annotations);
105 for (i = 0; i < n; ++i) {
106 if (annotations[i] == '\r')
107 annotations[i] = '\n';
108 }
109 memcpy(&typ, AnnoID, 4);
110 if (AIFF_SetAttribute(out, typ, annotations) < 1) {
111 AIFF_WriteClose(out);
112 return 0;
113 }
114 }
115 /* Go to 'startpos' */
116 ModPlug_SeekOrder(file.mod, startpos);
117
118 /* Now start writing the actual sound */
119 if (AIFF_StartWritingSamples(out) < 1) {
120 AIFF_WriteClose(out);
121 return 0;
122 }
123 while ((bytes_out = ModPlug_Read(file.mod, buffer, 65536)) > 0) {
124 if (bytes_out & 0x3) { /* if( bytes_out % 4 != 0 ) */
125 error("read error!\n");
126 break;
127 }
128 samples_read = bytes_out >> 2; /* bytes_out / 4 */
129 if (AIFF_WriteSamples32Bit(out, samples, samples_read) < 1) {
130 AIFF_WriteClose(out);
131 return 0;
132 }
133 /*
134 * Check if we have to finish reading
135 */
136 if (endpos > 0) {
137 order = ModPlug_GetCurrentOrder(file.mod);
138 if (order >= endpos)
139 break;
140 }
141 }
142
143 AIFF_EndWritingSamples(out);
144 AIFF_WriteClose(out);
145
146 notice("done\n");
147 return 1;
148 }
149