/[projet1]/public/pc/tools/osdk/main/SampleTweaker/main.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/SampleTweaker/main.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1258 - (show annotations)
Sat Feb 14 20:23:26 2015 UTC (4 years, 9 months ago) by dbug
File size: 11436 byte(s)
Did some tests on the sample conversion, but nothing worth making a new version really. Still need a lot of work.
1 //
2 //
3 //
4 #define _CRT_SECURE_NO_WARNINGS
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <memory.h>
9 #include <io.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <sys/stat.h>
13
14 #include <math.h>
15
16
17
18 /*
19 bug: having the output (your 0-255) in 0 <= y <= 1 gives "x = 15-2*(log10(1/y)/log10(2))"
20 <_Stefan> x is the psg volume from 0 to 15
21 */
22
23 unsigned char SampleToVolume(unsigned char sample)
24 {
25 if (!sample)
26 {
27 // To avoid a divide by 0
28 return 0;
29 }
30 else
31 {
32 double y=(double)sample;
33 y=y/255.0;
34
35 double x;
36 x = 15.0-2.0*(log10(1.0/y)/log10(2.0));
37
38 if (x<0.0)
39 {
40 x=0.0;
41 }
42 else
43 if (x>15.0)
44 {
45 x=15.0;
46 }
47 return (unsigned char)x;
48 }
49 }
50
51
52
53 bool LoadFile(const char *ptr_filename,unsigned char *&ptr_buffer,int &size)
54 {
55 struct _finddata_t file_info_src;
56 int result;
57
58 result=_findfirst(ptr_filename,&file_info_src);
59 if (result==-1.L)
60 {
61 return false;
62 }
63 _findclose(result);
64
65
66 size=file_info_src.size;
67
68 ptr_buffer=new unsigned char[size];
69
70 long handle;
71 long size_read;
72
73 if (!(handle=_open(ptr_filename,_O_RDONLY|_O_BINARY)))
74 {
75 return false;
76 }
77 size_read=_read(handle,ptr_buffer,size);
78 _close(handle);
79
80 if (size!=size_read)
81 {
82 // Read error
83 return false;
84 }
85
86 return true;
87 }
88
89
90
91 bool SaveFile(const char *ptr_filename,unsigned char *ptr_buffer,int size)
92 {
93 long handle;
94
95 if (!(handle=_open(ptr_filename,_O_TRUNC|O_BINARY|O_CREAT|O_WRONLY,_S_IREAD|_S_IWRITE )))
96 {
97 return false;
98 }
99 _write(handle,ptr_buffer,size);
100 _close(handle);
101
102 return true;
103 }
104
105
106
107
108
109 // Usage:
110 // FilePack <source_file> <dest_file>
111 //
112
113
114 void DisplayError()
115 {
116 printf("\n");
117 printf("\nÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
118 printf("\n³ 4bits Sample Merger ³");
119 printf("\n³ vers format ORIC ³");
120 printf("\n³ V0.001 ³");
121 printf("\n³ (c) 2002 POINTIER Mickael ³");
122 printf("\nÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
123 printf("\n");
124 exit(1);
125 }
126
127
128
129 #define NB_ARG 2
130
131
132 bool get_switch(const char *&ptr_arg,const char *ptr_switch)
133 {
134 int lenght=strlen(ptr_switch);
135
136 if (_memicmp(ptr_arg,ptr_switch,lenght))
137 {
138 // Not a match
139 return false;
140 }
141 // Validate the parameter
142 ptr_arg+=lenght;
143 return true;
144 }
145
146
147 int get_value(const char *&ptr_arg,long default_value)
148 {
149 char *ptr_end;
150 long value=strtoul(ptr_arg,&ptr_end,10);
151 if (ptr_arg==ptr_end)
152 {
153 value=default_value;
154 }
155 ptr_arg=ptr_end;
156 return value;
157 }
158
159
160 // Calculates log2 of number.
161 // http://www-crca.ucsd.edu/~msp/techniques/v0.08/book-html/node8.html
162 // http://poi.ribbon.free.fr/tmp/freq2regs.htm
163 // http://logbase2.blogspot.com/2007/12/log-base-2.html
164 //
165 // log2(1)=0
166 // log2(2)=1
167 // log2(4)=2
168 // log2(8)=4
169 float log2( double n )
170 {
171 // log(n)/log(2) is log2.
172 return (float)(log( n ) / log( 2.0 ));
173 }
174
175
176 void main(int argc,char *argv[])
177 {
178 long param;
179 long nb_arg;
180
181 bool flag_pack=true;
182 param=1;
183
184 if (argc>1)
185 {
186 for (;;)
187 {
188 nb_arg=argc;
189 const char *ptr_arg=argv[param];
190 /*
191 if (get_switch(ptr_arg,"-u")) // UNPACK
192 {
193 flag_pack=false;
194 argc--;
195 param++;
196 }
197 else
198 if (get_switch(ptr_arg,"-p")) // PACK
199 {
200 flag_pack=true;
201 argc--;
202 param++;
203 }
204 */
205 if (nb_arg==argc) break;
206 }
207 }
208
209
210 if (argc!=(NB_ARG+1))
211 {
212 DisplayError();
213 }
214
215
216 //
217 // Copy last parameters
218 //
219 char source_name[_MAX_PATH];
220 char dest_name[_MAX_PATH];
221
222 strcpy(source_name,argv[param]);
223 param++;
224 strcpy(dest_name,argv[param]);
225
226
227 unsigned char *ptr_buffer;
228 int size_buffer_src;
229
230 if (!LoadFile(source_name,ptr_buffer,size_buffer_src))
231 {
232 printf("\nUnable to load file '%s'",source_name);
233 printf("\n");
234 exit(1);
235 }
236
237 /*
238 //
239 // Stupid Raw=>nibble conversion, no frequency change
240 //
241 ptr_buffer_dst=new unsigned char[size_buffer_src+8];
242 size_buffer_dst=size_buffer_src/2;
243
244 unsigned char b0,b1,b;
245 int i;
246 unsigned char *ptr_src;
247 unsigned char *ptr_dst;
248
249 ptr_src=ptr_buffer;
250 ptr_dst=ptr_buffer_dst;
251 for (i=0;i<size_buffer_dst;i++)
252 {
253 b0=*ptr_src++;
254 b1=*ptr_src++;
255 b=(b1&0xF0)|(b0>>4);
256 *ptr_dst++=b;
257 }
258 */
259
260 //
261 // Try to adapt the size of dest buffer based on complex calculations:
262 // Move from source frequency to dest frequency, while trying to round
263 // on a multiple of 80 samples (or 40 bytes)
264 //
265 //size_buffer_dst=(size_buffer_src*4000)/44100; // overflow and get negative on a 581114 bytes sample...
266
267 /*
268 int delta=size_buffer_dst%80;
269 if (!delta)
270 {
271 // Perfectly on a 80 multiple (yoohoo)
272 }
273 else
274 if (delta<40)
275 {
276 // Reduce the size of dest buffer
277 size_buffer_dst-=delta;
278 }
279 else
280 {
281 // Increase the size of dest buffer
282 size_buffer_dst-=delta;
283 size_buffer_dst+=80;
284 }
285 */
286
287 int size_buffer_dst;
288 unsigned char *ptr_buffer_dst;
289
290 // 4.b 'RIFF'
291 // 4.b size
292 // 4.b 'WAVE'
293 // 4.b 'fmt '
294 #if 0 // ATARI DELTA PACK CODE
295 size_buffer_dst=1+(size_buffer_src/2);
296 ptr_buffer_dst=new unsigned char[size_buffer_dst+1];
297
298 // Stores a first byte which is the starting value,
299 // then encode each value as a 4 bit signed delta relative to the first value
300 unsigned char *ptr_src=ptr_buffer;
301 unsigned char *ptr_dst=ptr_buffer_dst;
302
303 // Store first byte twice, so the delta are not on an odd address
304 unsigned char prev=ptr_src[0];
305 *ptr_dst++=prev;
306
307 bool flip=false;
308 unsigned char store=0;
309
310 // Then compute the deltas, they will match the following table:
311 // Delta: 0 1 2 4 8 16 32 64 128 -64 -32 -16 -8 -4 -2 -1
312 // Code: $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $A $B $C $D $E $F
313 char delta_table[16]=
314 {
315 -64,
316 -32,
317 -16,
318 -8,
319 -4,
320 -2,
321 -1,
322 0,
323 1,
324 2,
325 4,
326 8,
327 16,
328 32,
329 64,
330 127
331 };
332
333 int delta_usage[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
334
335
336 for (int i=1;i<size_buffer_src;i++)
337 {
338 unsigned char delta_index;
339
340 unsigned char next=ptr_src[i];
341
342 int max_error=999;
343 delta_index=0;
344 for (int delta_entry=0;delta_entry<16;delta_entry++)
345 {
346 unsigned char new_next=prev+delta_table[delta_entry];
347 int error=next-new_next;
348 if (error<0)
349 {
350 error=-error;
351 }
352 /*
353 if (error>127)
354 {
355 __asm int 3
356 }
357 */
358 if (error<max_error)
359 {
360 max_error=error;
361 delta_index=delta_entry;
362 if (max_error==0)
363 {
364 // Can't do better than no error
365 break;
366 }
367 }
368 }
369
370 unsigned char delta_value=delta_table[delta_index];
371 delta_usage[delta_index]++;
372 prev+=delta_value;
373
374 store<<=4;
375 store|=delta_index;
376 flip=!flip;
377 if (!flip)
378 {
379 *ptr_dst++=store;
380 }
381 }
382
383 #else // ORIC 4BIT CODE
384 size_buffer_dst=(size_buffer_src/2)+1; // +1 for the 00 final
385 ptr_buffer_dst=new unsigned char[size_buffer_dst];
386
387 // ln(1) -> 0
388 // ln(2) -> 0.6931
389 // ln(16) -> 2.77
390
391 // log(1)=0
392 // log(16)=1.204
393 // 1/log(16)= 0.830482
394 // ACHANGERDESUITE
395
396
397 // Volume levels
398 int voltab[] = { 0, 513/257, 828/257, 1239/257, 1923/257, 3238/257, 4926/257, 9110/257, 10344/257, 17876/257, 24682/257, 30442/257, 38844/257, 47270/257, 56402/257, 65535/257};
399
400 // Create a log table
401 // 15 -> 1.0 -> 255
402 // 14 -> 0.707 -> 180,285
403 // 13 -> 0.5 -> 128
404 // 12 -> 0.303 -> 77,265
405 // 11 -> 0.25 -> 63,75
406 // 10 -> 0.1515 -> 38,6325
407 // 9 -> 0.125 -> 31,875
408 // 8 -> ?
409 // 7 -> 0,0625 -> 15,9375
410 // 6 -> ?
411 // 5 -> 0,03125 -> 7,96875
412 // 4 -> ?
413 // 3 -> 0,015625 -> 3,984375
414 // 2 -> ?
415 // 1 -> 0,0078125 -> 1,9921875
416 // 0 -> 0
417 unsigned char logVolume[256];
418 int vol=0;
419 for (int i=0;i<16;i++)
420 {
421 int maxvol=voltab[i];
422 while (vol<=maxvol)
423 {
424 logVolume[vol]=i;
425 vol++;
426 }
427 }
428
429 // Convert to 4 bit sample,
430 // each byte contains to sample values; one per nibble
431 unsigned char *ptr_src=ptr_buffer;
432 unsigned char *ptr_dst=ptr_buffer_dst;
433 for (int i=0;i<(size_buffer_dst-1);i++)
434 {
435 #if 1
436 // Log conversion
437 unsigned char b0=*ptr_src++;
438 b0=logVolume[b0]; //>>4;
439
440 unsigned char b1=*ptr_src++;
441 b1=logVolume[b1]; //>>4;
442 unsigned char b=(b1<<4)|(b0);
443 #else
444 /*
445 // Raw conversion
446 unsigned char b0=*ptr_src++;
447 b0=(((unsigned int)b0)*15)/255;
448
449 unsigned char b1=*ptr_src++;
450 b1=(((unsigned int)b1)*15)/255;
451
452 unsigned char b=(b1<<4)|(b0);
453 */
454 // Error based conversion
455 unsigned char b0=*ptr_src++;
456 b0=(((unsigned int)b0)*15)/255;
457
458 unsigned char b1=*ptr_src++;
459 b1=(((unsigned int)b1)*15)/255;
460
461 unsigned char b=(b1<<4)|(b0);
462 #endif
463
464 if (!b)
465 {
466 // To avoid a spurious null terminator
467 //b=1;
468 }
469 *ptr_dst++=b;
470 }
471 // Null terminator
472 *ptr_dst++=0;
473 #endif
474
475 #if 0
476 // Depack and save in the source file :p
477 ptr_src=ptr_buffer_dst;
478 ptr_dst=ptr_buffer;
479
480 // Store first byte
481 prev=ptr_src[0];
482 *ptr_dst++=prev;
483
484 for (int i=1;i<size_buffer_dst;i++)
485 {
486 unsigned char store=ptr_src[i];
487 unsigned char b1=(store&15);
488 unsigned char b0=((store>>4)&15);
489
490 prev+=delta_table[b0];
491 *ptr_dst++=prev;
492
493 prev+=delta_table[b1];
494 *ptr_dst++=prev;
495 }
496
497 if (!SaveFile(dest_name,ptr_buffer,size_buffer_src))
498 {
499 printf("\nUnable to save file '%s'",source_name);
500 printf("\n");
501 exit(1);
502 }
503 #else
504 // Save the resulting file
505 if (!SaveFile(dest_name,ptr_buffer_dst,size_buffer_dst))
506 {
507 printf("\nUnable to save file '%s'",source_name);
508 printf("\n");
509 exit(1);
510 }
511 #endif
512
513 //
514 // Make some cleaning
515 //
516 delete[] ptr_buffer;
517 delete[] ptr_buffer_dst;
518 }
519
520
521 /*
522
523 15 1.0
524 14 0.707 <= 0.606 ???
525 13 0.5
526 12 0.303
527 11 0.25
528 10 0.1515
529 9 0.125
530 8 0.07575
531 7 0.0625
532 6 0.037875
533 5 0.03125
534 4 0.0189375
535 3 0.015625
536 2 0.00946875
537 1 0.0078125
538 0 0.0
539
540
541 V[13]=V[15]/2
542
543
544
545 // calculate the volume->voltage conversion table
546 // The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step)
547 // The YM2149 still has 16 levels for the tone generators, but 32 for
548 // the envelope generator (1.5dB per step).
549 for (i = 31;i > 0;i--)
550 {
551 // limit volume to avoid clipping
552 if (out > MAX_OUTPUT) PSG->VolTable[i] = MAX_OUTPUT;
553 else PSG->VolTable[i] = (unsigned int)out;
554
555 if (AY_filetype==0)
556 out = out - (MAX_OUTPUT / 32);
557 else
558 out /= 1.188502227; // = 10 ^ (1.5/20) = 1.5dB
559 }
560
561
562
563 Volume Dac output Volume Raw Corrected
564 Corrected
565
566 15 1.0 15.0 255 255
567 14 0.707 12.62 238
568 13 0.5 10.61 221
569 12 0.303 8.93 204
570 11 0.25 7.51 187
571 10 0.1515 6.32 170
572 9 0.125 5.32 153
573 8 0.07575 4.47 136
574 7 0.0625 3.76 119
575 6 0.037875 3.17 102
576 5 0.03125 2.66 85
577 4 0.0189375 2.244 68
578 3 0.015625 1.888 51
579 2 0.00946875 1.58 34
580 1 0.0078125 1.33 17
581 0 0.0 0.0 0 0
582
583 */

  ViewVC Help
Powered by ViewVC 1.1.26