1 /* $Id: pcm_write.c,v 1.5 2006/09/16 10:02:29 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  *   PCM FILE / AUDIO WRITER
19  * ==========================
20  */
21 
22 #include <umodplayer.h>
23 #include <coresound.h>
24 
25 EXPORT unsigned long
WritePCM(char * rfile,int format)26 WritePCM(char *rfile, int format)
27 {
28 	int order;
29 	int16_t samples[5000];
30 	char *buffer = (char *) samples;
31 	int e, d;
32 	int fd;
33 	int bytes_out, epos, upos, bytes_in;
34 	unsigned long length = 0;
35 	char *endian;
36 
37 	fd = open(rfile, O_WRONLY | O_TRUNC | O_CREAT, 0644);
38 	if (fd == -1) {
39 		return 0;
40 	}
41 	ModPlug_SeekOrder(file.mod, startpos);
42 
43 	/* Use 16-bit samples */
44 	CoreSound_BitsPerSample = 16;
45 	CoreSound_InitOptions();
46 
47 	if (format & EXPORT_BIG_ENDIAN) {
48 		endian = "big-endian";
49 	} else if (format & EXPORT_LTE_ENDIAN) {
50 		endian = "little-endian";
51 	} else {
52 		if (sets.endianness == BIG_ENDIAN) {
53 			endian = "big-endian";
54 		} else {
55 			endian = "little-endian";
56 		}
57 	}
58 
59 	notice("Exporting audio to raw 16-bit PCM, %s, sampling rate: %.3f kHz\n",
60 	        endian, ((double) sets.samplerate) / 1000.0);
61 
62 	while ((bytes_out = ModPlug_Read(file.mod, buffer, 10000)) > 0) {
63 		length += bytes_out;
64 
65 		/* Calculate the number of short values entered in buffer */
66 		d = bytes_out >> 1;	/* bytes_out / 2 */
67 
68 		/*
69 		 * Byteswap if required
70 		 */
71 		if ((sets.endianness == BIG_ENDIAN && (format & EXPORT_LTE_ENDIAN)) ||
72 		    (sets.endianness == LTE_ENDIAN && (format & EXPORT_BIG_ENDIAN)))
73 		{
74 			for (e = 0; e < d; ++e) {
75 				samples[e] = swap16(samples[e]);
76 			}
77 		}
78 
79 		/*
80 		 * Write the data to the file.
81 		 * If the system cant write the 10000-bytes buffer all in one,
82 		 * we use many write() calls.
83 		 *
84 		 * This can be useful for pipes (since raw PCM audio can
85 		 * be piped in example to a player program).
86 		 */
87 		upos = 0;
88 		bytes_in = bytes_out;
89 		for (;;) {
90 			epos = write(fd, buffer + upos, bytes_in);
91 			if (epos < 1) {
92 				close(fd);
93 				return 0;
94 			}
95 			if (epos == bytes_in)
96 				break;
97 			upos += epos;
98 			bytes_in -= epos;
99 		}
100 
101 		/*
102 	         * Check if we have to finish reading
103 	         */
104 		if (endpos > 0) {
105 			order = ModPlug_GetCurrentOrder(file.mod);
106 			if (order >= endpos)
107 				break;
108 		}
109 	}
110 
111 	close(fd);
112 	notice("done!\n");
113 	return length;
114 }
115