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