1 /* wavbreaker - A tool to split a wave file up into multiple wave.
2  * Copyright (C) 2002 Timothy Robinson
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 #include <stdio.h>
20 #include <sys/stat.h>
21 #include "cdda.h"
22 
23 unsigned long file_size;
24 
25 int
cdda_read_header(const char * filename,SampleInfo * sampleInfo)26 cdda_read_header(const char *filename,
27                  SampleInfo *sampleInfo)
28 {
29 	struct stat statBuf;
30 
31 	if (stat(filename, &statBuf)) {
32 		printf("error stat'ing %s\n", filename);
33 		return -1;
34 	}
35 
36 	file_size = statBuf.st_size;
37 
38 	sampleInfo->numBytes = statBuf.st_size;
39 	sampleInfo->channels = 2;
40 	sampleInfo->samplesPerSec = 44100;
41 	sampleInfo->bitsPerSample = 16;
42         sampleInfo->avgBytesPerSec = sampleInfo->bitsPerSample/8 * sampleInfo->samplesPerSec * sampleInfo->channels;
43         sampleInfo->blockAlign = 4;
44 
45 	return 0;
46 }
47 
48 int
cdda_read_sample(FILE * fp,unsigned char * buf,int buf_size,unsigned long start_pos)49 cdda_read_sample(FILE *fp,
50                  unsigned char *buf,
51                  int buf_size,
52                  unsigned long start_pos)
53 {
54 	int i = 0;
55 	int ret;
56 
57 	if (fseek(fp, start_pos, SEEK_SET)) {
58 		return -1;
59 	}
60 
61 	if (start_pos > file_size) {
62 		return -1;
63 	}
64 
65 	ret = fread(buf, 1, buf_size, fp);
66 
67 	for (i = 0; i < ret / 4; i++) {
68 		unsigned char tmp;
69 
70 		/* left channel */
71 		tmp = buf[i*4+0];
72 		buf[i*4+0] = buf[i*4+1];
73 		buf[i*4+1] = tmp;
74 
75 		/* right channel */
76 		tmp = buf[i*4+2];
77 		buf[i*4+2] = buf[i*4+3];
78 		buf[i*4+3] = tmp;
79 	}
80 
81 	return ret;
82 }
83 
84 int
cdda_write_file(FILE * fp,char * filename,int buf_size,unsigned long start_pos,unsigned long end_pos)85 cdda_write_file(FILE *fp,
86                 char *filename,
87                 int buf_size,
88                 unsigned long start_pos,
89                 unsigned long end_pos)
90 {
91 	int ret;
92 	FILE *new_fp;
93 	unsigned long cur_pos;
94 	unsigned char buf[buf_size];
95 
96 	if ((new_fp = fopen(filename, "wb")) == NULL) {
97 		printf("error opening %s for writing\n", filename);
98 		return -1;
99 	}
100 
101 	cur_pos = start_pos;
102 
103 	if (fseek(fp, cur_pos, SEEK_SET)) {
104 		fclose(new_fp);
105 		return -1;
106 	}
107 
108 	if (cur_pos > file_size) {
109 		fclose(new_fp);
110 		return -1;
111 	}
112 
113 	/* DEBUG CODE START */
114 
115 	printf("start_pos: %lu\n", start_pos);
116 	printf("end_pos: %lu\n", end_pos);
117 	printf("cur_pos: %lu\n", cur_pos);
118 
119 	/* DEBUG CODE END */
120 
121 	if (cur_pos + buf_size > end_pos && end_pos != 0) {
122 		buf_size = end_pos - cur_pos;
123 	}
124 	while ((ret = fread(buf, 1, buf_size, fp)) > 0 &&
125 				(cur_pos < end_pos || end_pos == 0)) {
126 
127 		if ((fwrite(buf, 1, ret, new_fp)) < ret) {
128 			printf("error writing to file %s\n", filename);
129 			fclose(new_fp);
130 			return -1;
131 		}
132 		cur_pos += ret;
133 
134 		if (cur_pos + buf_size > end_pos && end_pos != 0) {
135 			buf_size = end_pos - cur_pos;
136 		}
137 	}
138 
139 	/* DEBUG CODE START */
140 	printf("cur_pos: %lu\n", cur_pos);
141 	printf("done writing - %s\n\n", filename);
142 	/* DEBUG CODE END */
143 
144 	fclose(new_fp);
145 	return ret;
146 }
147