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