PS2SDK
PS2 Homebrew Libraries
main.c
1 #include <stdio.h>
2 #include <errno.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <math.h>
6 
7 #define VERSION "1.2"
8 
9 extern int adpcm_encode(FILE* fp, FILE* sad, int offset, int sample_len, int flag_loop, int bytes_per_sample);
10 
11 enum{ monoF = (1 << 0), stereo = (1 << 1), loopF = (1 << 2) } sad_flag;
12 
13 struct AdpcmHeader{
14  char id[4]; //"APCM"
15  unsigned char version;
16  unsigned char channels;
17  unsigned char loop;
18  unsigned char reserved;
19  unsigned int pitch;
20  unsigned int samples;
21 };
22 
23 static int ConvertFile(const char *InputFile, const char *OutputFile, int flag_loop){
24  FILE *fp, *sad;
25  int sample_freq, sample_len, result;
26  char s[4];
27  int chunk_data;
28  short e;
29  char channels;
30  char bytes_per_sample;
31  struct AdpcmHeader AdpcmHeader;
32 
33  result=0;
34  if ( (fp = fopen(InputFile, "rb" )) != NULL )
35  {
36  if (fread( s, 1, 4, fp )!=4 || strncmp( s, "RIFF", 4 ) )
37  {
38  printf( "Error: Not a WAVE-file (\"RIFF\" identifier not found)\n" );
39  result=-3;
40  goto InputFileIOEnd;
41  }
42 
43  fseek( fp, 8, SEEK_SET );
44 
45  if (fread( s, 1, 4, fp )!=4 || strncmp( s, "WAVE", 4 ) )
46  {
47  printf( "Error: Not a WAVE-file (\"WAVE\" identifier not found)\n" );
48  result=-3;
49  goto InputFileIOEnd;
50  }
51 
52  fseek( fp, 8 + 4, SEEK_SET );
53 
54  if (fread( s, 1, 4, fp )!=4 || strncmp( s, "fmt", 3 ) )
55  {
56  printf( "Error: Not a WAVE-file (\"fmt\" chunk not found)\n" );
57  result=-3;
58  goto InputFileIOEnd;
59  }
60 
61  if(fread( &chunk_data, 4, 1, fp )==1){
62  chunk_data += ftell( fp );
63 
64  if (fread( &e, 2, 1, fp )!=1 || e != 1 )
65  {
66  printf( "Error: No PCM data in WAVE-file\n" );
67  result=-4;
68  goto InputFileIOEnd;
69  }
70  }
71  else{
72  printf( "Error: can't read CHUNK DATA in WAVE-file\n" );
73  result=-4;
74  goto InputFileIOEnd;
75  }
76 
77  if (fread( &e, 2, 1, fp )!=1 || ((e != 1) && (e != 2)))
78  {
79  printf( "Error: WAVE file must be MONO or STEREO (max 2 channels)\n" );
80  result=-5;
81  goto InputFileIOEnd;
82  }
83 
84  channels = e;
85 
86  if(fread( &sample_freq, 4, 1, fp )==1){
87  fseek( fp, 4 + 2, SEEK_CUR );
88  if (fread( &e, 2, 1, fp )!=1 || (e != 8 && e != 16) )
89  {
90  printf( "Error: WAVE-file must 8 or 16 bit\n" );
91  result=-6;
92  goto InputFileIOEnd;
93  }
94  bytes_per_sample = e / 8;
95  }
96  else{
97  printf("Error: Can't read SAMPLE FREQUENCY in WAVE-file\n");
98  result=-6;
99  goto InputFileIOEnd;
100  }
101 
102  fseek( fp, chunk_data, SEEK_SET );
103  if(fread( s, 1, 4, fp )==4){
104  // Skip 'fact' and possibly other chunks
105  while(strncmp( s, "data", 4 ))
106  {
107  if(fread( &chunk_data, 4, 1, fp )==1){
108  chunk_data += ftell( fp );
109  fseek( fp, chunk_data, SEEK_SET );
110  if(fread( s, 1, 4, fp )!=4){
111  printf("Error: Read error in WAVE-file\n");
112  result=-6;
113  goto InputFileIOEnd;
114  }
115  }
116  else{
117  printf("Error: Read error in WAVE-file\n");
118  result=-6;
119  goto InputFileIOEnd;
120  }
121  }
122  }
123  else{
124  printf("Error: Read error in WAVE-file\n");
125  result=-6;
126  goto InputFileIOEnd;
127  }
128 
129  if(fread( &sample_len, 4, 1, fp )==1){
130  sample_len /= (channels*bytes_per_sample);
131  }
132  else{
133  printf("Error: Can't read SAMPLE LENGTH in WAVE-file\n");
134  result=-6;
135  goto InputFileIOEnd;
136  }
137 
138  if ( (sad = fopen(OutputFile, "wb" )) != NULL )
139  {
140  AdpcmHeader = (struct AdpcmHeader)
141  {
142  .id="APCM",
143  .version=1,
144  .channels=channels,
145  .loop=flag_loop,
146  .reserved=0,
147  .pitch=(sample_freq*4096)/48000, // pitch, to encode for PS1 change 48000 to 44100
148  .samples=sample_len
149  };
150  fwrite(&AdpcmHeader, sizeof(AdpcmHeader), 1, sad);
151 
152  if(channels == 1)
153  {
154  result=adpcm_encode(fp, sad, 0, sample_len, flag_loop, bytes_per_sample);
155  }
156  else
157  {
158  int data_offset = ftell(fp);
159 
160  // Encode left
161  if((result=adpcm_encode(fp, sad, bytes_per_sample, sample_len, flag_loop, bytes_per_sample))==0){
162  fseek(fp, data_offset+bytes_per_sample, SEEK_SET);
163  // Encode right
164  result=adpcm_encode(fp, sad, bytes_per_sample, sample_len, flag_loop, bytes_per_sample);
165  }
166  }
167 
168  fclose(sad);
169  }
170  else
171  {
172  printf( "Error: Can't write output file %s\n", OutputFile);
173  result=EIO;
174  }
175 
176 InputFileIOEnd:
177  fclose(fp);
178  }
179  else
180  {
181  printf( "Error: Can't open %s\n", InputFile);
182  result=ENOENT;
183  }
184 
185  return result;
186 }
187 
188 int main( int argc, char *argv[] )
189 {
190  int result;
191 
192  if( argc == 4)
193  {
194  if( strncmp( argv[1], "-L", 2 ) )
195  {
196  printf("Error: Option '%s' not recognized\n", argv[1]);
197  result=EINVAL;
198  }
199  else
200  {
201  result=ConvertFile(argv[2], argv[3], 1);
202  }
203  }
204  else if(argc == 3)
205  {
206  result=ConvertFile(argv[1], argv[2], 0);
207  }
208  else
209  {
210  printf( "ADPCM Encoder %s\n"
211  "Usage: sadenc [-L] <input wave> <output sad>\n"
212  "Options:\n"
213  " -L Loop\n", VERSION);
214  result=EINVAL;
215  }
216 
217  return result;
218 }
EIO
#define EIO
Definition: errno.h:29
ENOENT
#define ENOENT
Definition: errno.h:23
ctype.h
AdpcmHeader
Definition: main.c:13
stdio.h
EINVAL
#define EINVAL
Definition: errno.h:63
errno.h