00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <iostream.h>
00039 #include <iomanip.h>
00040 #include <fstream.h>
00041
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #ifdef __MSDOS__
00046 #include <dir.h>
00047 #endif
00048 #include <time.h>
00049
00050 #include "player.h"
00051 #include "myendian.h"
00052
00053 #if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
00054 #error Have to define the endianess of the cpu.
00055 #endif
00056
00057 #if defined(__amigaos__)
00058 #define EXIT_ERROR_STATUS (20)
00059 #else
00060 #define EXIT_ERROR_STATUS (-1)
00061 #endif
00062
00063 const char s2w_version[] = "1.7.2";
00064
00065 enum
00066 {
00067 TXT_TITLE,
00068 ERR_NOT_ENOUGH_MEMORY,
00069 ERR_SYNTAX, ERR_ENGINE,
00070 ERR_ENDIANESS
00071 };
00072
00073 const int FLAG_STDIN = 0x01;
00074 const int FLAG_ULAW = 0x08;
00075
00076 static int flags;
00077
00078 struct wav_hdr
00079 {
00080 char main_chunk[4];
00081 udword length;
00082 char chunk_type[4];
00083
00084 char sub_chunk[4];
00085 udword clength;
00086 uword format;
00087 uword modus;
00088 udword samplefreq;
00089 udword bytespersec;
00090 uword bytespersmpl;
00091 uword bitspersmpl;
00092 char data_chunk[4];
00093 udword data_length;
00094 };
00095
00096 struct au_hdr
00097 {
00098 char id[4];
00099 udword hdrlength;
00100 udword length;
00101 udword format;
00102 udword frequency;
00103 udword channels;
00104
00105
00106
00107 };
00108
00109
00110 #if defined(IS_LITTLE_ENDIAN)
00111 wav_hdr my_wav_hdr =
00112 {
00113 {'R','I','F','F'}, 0, {'W','A','V','E'},
00114 {'f','m','t',' '}, 16, 1, 1, 22050, 22050, 1, 8,
00115 {'d','a','t','a'}, 0
00116 };
00117 #else
00118 wav_hdr my_wav_hdr =
00119 {
00120 {'R','I','F','F'}, 0, {'W','A','V','E'},
00121 {'f','m','t',' '},
00122 convertEndianess ((udword)16),
00123 convertEndianess ((uword)1),
00124 convertEndianess ((uword)1),
00125 convertEndianess ((udword)22050),
00126 convertEndianess ((udword)22050),
00127 convertEndianess ((uword)1),
00128 convertEndianess ((uword)8),
00129 {'d','a','t','a'}, 0
00130 };
00131 #endif
00132
00133 #if defined(IS_LITTLE_ENDIAN)
00134 au_hdr my_au_hdr =
00135 {
00136 {'.','s','n','d'},
00137 convertEndianess ((udword)0x18),
00138 0,
00139 convertEndianess ((udword)1),
00140 convertEndianess ((udword)8000),
00141 convertEndianess ((udword)1)
00142 };
00143 #else
00144 au_hdr my_au_hdr =
00145 {
00146 {'.','s','n','d'}, 0x18, 0, 1, 8000, 1
00147 };
00148 #endif
00149
00150 static int fadein_seconds,
00151 fadein_step,
00152 fadein_count,
00153 fadein_currentlevel,
00154 fadeout_seconds,
00155 fadeout_step,
00156 fadeout_count,
00157 fadeout_currentlevel,
00158 fadelevel;
00159
00160
00161 void error( char*, char* );
00162 void printtext( int );
00163
00164 void (*fadeout_buffer)( ubyte*, udword );
00165 void (*fadein_buffer)( ubyte*, udword );
00166
00167 void fadeout_buffer_8( ubyte*, udword );
00168 void fadein_buffer_8( ubyte*, udword );
00169 void fadeout_buffer_16( ubyte*, udword );
00170 void fadein_buffer_16( ubyte*, udword );
00171 void buffer2ulaw( ubyte* samplebuffer, udword samplebuffersize );
00172 void endianswitch_buffer( ubyte* samplebuffer, udword samplebuffersize );
00173
00174
00175 int main(int argc, char *argv[])
00176 {
00177
00178 printtext(TXT_TITLE);
00179
00180
00181
00182
00183
00184
00185 emuEngine myEmuEngine;
00186
00187 if ( !myEmuEngine )
00188 {
00189
00190 printtext(ERR_NOT_ENOUGH_MEMORY);
00191 }
00192 if ( !myEmuEngine.verifyEndianess() )
00193 {
00194 printtext(ERR_ENDIANESS);
00195 }
00196
00197 struct emuConfig myEmuConfig;
00198 myEmuEngine.returnConfig(myEmuConfig);
00199
00200
00201
00202
00203
00204
00205 myEmuConfig.frequency = 22050;
00206 myEmuConfig.channels = SIDEMU_MONO;
00207 myEmuConfig.bitsPerSample = SIDEMU_8BIT;
00208 flags = 0;
00209 uword selectedSong = 0;
00210 int seconds = 60;
00211 int beginSeconds = 0;
00212 fadein_seconds = 0;
00213 fadeout_seconds = 2;
00214 fadeout_buffer = fadeout_buffer_8;
00215 fadein_buffer = fadein_buffer_8;
00216 int muteVal = 0;
00217
00218
00219 int infile = 0, outfile = 0;
00220
00221
00222 for ( int a = 1; a < argc; a++)
00223 {
00224 if ( argv[a][0] == '-')
00225 {
00226 #ifndef __MSDOS__
00227
00228 if ( strlen(argv[a]) == 1 )
00229 {
00230 if ( infile == 0 )
00231 {
00232 infile = a;
00233 flags |= FLAG_STDIN;
00234 }
00235 else
00236 {
00237 printtext(ERR_SYNTAX);
00238 }
00239 break;
00240 }
00241 #endif
00242 if ( strncasecmp( &argv[a][1], "fout", 4 ) == 0 )
00243 {
00244 fadeout_seconds = atoi(argv[a]+5);
00245 }
00246 else if ( strncasecmp( &argv[a][1], "fin", 3 ) == 0 )
00247 {
00248 fadein_seconds = atoi(argv[a]+4);
00249 }
00250 else if ( strncasecmp( &argv[a][1], "nf", 2 ) == 0 )
00251 {
00252 myEmuConfig.emulateFilter = false;
00253 }
00254 else if ( strncasecmp( &argv[a][1], "a2", 2 ) == 0 )
00255 {
00256 myEmuConfig.memoryMode = MPU_BANK_SWITCHING;
00257 }
00258 else if ( strncasecmp( &argv[a][1], "a", 1 ) == 0 )
00259 {
00260 myEmuConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
00261 }
00262 else if ( strncasecmp( &argv[a][1], "b", 1 ) == 0 )
00263 {
00264 beginSeconds = atoi(argv[a]+2);
00265 }
00266 else if ( strncasecmp( &argv[a][1], "f", 1 ) == 0 )
00267 {
00268 myEmuConfig.frequency = (ulong)atoi(argv[a]+2);
00269 }
00270 else if ( strncasecmp( &argv[a][1], "h", 1 ) == 0 )
00271 {
00272 printtext(ERR_SYNTAX);
00273 }
00274 else if ( strncasecmp( &argv[a][1], "m", 1 ) == 0 )
00275 {
00276 for ( ubyte j = 2; j < strlen(argv[a]); j++ )
00277 {
00278 if ( (argv[a][j]>='1') && (argv[a][j]<='4') )
00279 {
00280 muteVal |= (1 << argv[a][j]-'1');
00281 }
00282 }
00283 myEmuConfig.volumeControl = SIDEMU_VOLCONTROL;
00284 }
00285 else if ( strncasecmp( &argv[a][1], "n", 1 ) == 0 )
00286 {
00287 myEmuConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
00288 myEmuConfig.forceSongSpeed = true;
00289 }
00290 else if ( strncasecmp( &argv[a][1], "o", 1 ) == 0 )
00291 {
00292 selectedSong = atoi(argv[a]+2);
00293 }
00294 else if ( strncasecmp( &argv[a][1], "t", 1 ) == 0 )
00295 {
00296 seconds = atoi(argv[a]+2);
00297 }
00298 else if ( strncasecmp( &argv[a][1], "ss", 2 ) == 0 )
00299 {
00300 myEmuConfig.channels = SIDEMU_STEREO;
00301 myEmuConfig.volumeControl = SIDEMU_STEREOSURROUND;
00302 }
00303 else if ( strncasecmp( &argv[a][1], "s", 1 ) == 0 )
00304 {
00305 myEmuConfig.channels = SIDEMU_STEREO;
00306 }
00307 else if ( strncasecmp( &argv[a][1], "u", 1 ) == 0 )
00308 {
00309 flags |= FLAG_ULAW;
00310 }
00311 else if ( strncasecmp( &argv[a][1], "16", 2 ) == 0 )
00312 {
00313 myEmuConfig.bitsPerSample = SIDEMU_16BIT;
00314 }
00315 else
00316 {
00317 printtext(ERR_SYNTAX);
00318 }
00319 }
00320 else
00321 {
00322
00323 if ( infile == 0 )
00324 {
00325 infile = a;
00326 }
00327 else if ( outfile == 0 )
00328 {
00329 outfile = a;
00330 }
00331 else
00332 {
00333 printtext(ERR_SYNTAX);
00334 }
00335 }
00336 }
00337
00338 if ( infile == 0 )
00339 {
00340 printtext(ERR_SYNTAX);
00341 }
00342
00343
00344
00345 if (flags & FLAG_ULAW)
00346 {
00347 myEmuConfig.frequency = 8000;
00348 myEmuConfig.channels = SIDEMU_MONO;
00349 myEmuConfig.bitsPerSample = SIDEMU_16BIT;
00350 }
00351 if (myEmuConfig.bitsPerSample == SIDEMU_16BIT)
00352 {
00353 fadeout_buffer = fadeout_buffer_16;
00354 fadein_buffer = fadein_buffer_16;
00355 }
00356
00357 #ifdef __MSDOS__
00358 char outpathname[MAXPATH];
00359 if ( outfile == 0 )
00360 {
00361 char indrive[MAXDRIVE], inpath[MAXDIR], inname[MAXFILE], inext[MAXEXT];
00362 fnsplit(argv[infile], indrive, inpath, inname, inext);
00363 fnmerge(outpathname, indrive, inpath, inname, ".wav");
00364 }
00365 else
00366 {
00367 strcpy(outpathname, argv[outfile]);
00368 }
00369 #else
00370 char* outpathname;
00371 if ( outfile == 0 )
00372 {
00373 outpathname = new char[ strlen(argv[infile]) +4 +1];
00374 strcpy( outpathname, argv[infile] );
00375 if ( flags & FLAG_ULAW )
00376 {
00377 strcat( outpathname, ".au" );
00378 }
00379 else
00380 {
00381 strcat( outpathname, ".wav" );
00382 }
00383 }
00384 else
00385 {
00386 if (( outpathname = strdup( argv[outfile] )) == 0 )
00387 {
00388 printtext(ERR_NOT_ENOUGH_MEMORY);
00389 }
00390 }
00391 #endif
00392
00393
00394 sidTune myTune( argv[infile] );
00395 struct sidTuneInfo mySidInfo;
00396 myTune.returnInfo( mySidInfo );
00397 if ( !myTune )
00398 {
00399 cerr << mySidInfo.statusString << endl;
00400 exit(EXIT_ERROR_STATUS);
00401 }
00402 else
00403 {
00404 cout << "File format : " << mySidInfo.formatString << endl;
00405 cout << "Condition : " << mySidInfo.statusString << endl;
00406 if ( mySidInfo.numberOfInfoStrings == 3 )
00407 {
00408 cout << "Name : " << mySidInfo.nameString << endl;
00409 cout << "Author : " << mySidInfo.authorString << endl;
00410 cout << "Copyright : " << mySidInfo.copyrightString << endl;
00411 }
00412 else
00413 {
00414 for ( int infoi = 0; infoi < mySidInfo.numberOfInfoStrings; infoi++ )
00415 {
00416 cout << "Description : " << mySidInfo.infoString[infoi] << endl;
00417 }
00418 }
00419 cout << "Load address : $" << hex << setw(4) << setfill('0')
00420 << mySidInfo.loadAddr << endl;
00421 cout << "Init address : $" << hex << setw(4) << setfill('0')
00422 << mySidInfo.initAddr << endl;
00423 cout << "Play address : $" << hex << setw(4) << setfill('0')
00424 << mySidInfo.playAddr << dec << endl;
00425 }
00426
00427
00428 myEmuConfig.sampleFormat = (myEmuConfig.bitsPerSample == SIDEMU_16BIT) ? SIDEMU_SIGNED_PCM : SIDEMU_UNSIGNED_PCM;
00429 myEmuEngine.setConfig(myEmuConfig);
00430
00431 if (myEmuConfig.volumeControl == SIDEMU_VOLCONTROL)
00432 {
00433 for ( int voice = 1; voice <= 4; voice++ )
00434 {
00435 if ( (muteVal & (1<<(voice-1))) != 0 )
00436 {
00437 myEmuEngine.setVoiceVolume(voice,0,0,0);
00438 }
00439 }
00440 }
00441
00442
00443 myEmuEngine.returnConfig(myEmuConfig);
00444
00445 cout << "SID Filter : " << ((myEmuConfig.emulateFilter == true) ? "Yes" : "No") << endl;
00446 if (myEmuConfig.memoryMode == MPU_PLAYSID_ENVIRONMENT)
00447 {
00448 cout << "Memory mode : PlaySID (this is supposed to fix PlaySID-specific rips)" << endl;
00449 }
00450 else if (myEmuConfig.memoryMode == MPU_TRANSPARENT_ROM)
00451 {
00452 cout << "Memory mode : Transparent ROM (SIDPLAY default)" << endl;
00453 }
00454 else if (myEmuConfig.memoryMode == MPU_BANK_SWITCHING)
00455 {
00456 cout << "Memory mode : Bank Switching" << endl;
00457 }
00458 cout << "Frequency : " << dec << myEmuConfig.frequency << " Hz" << endl;
00459 cout << "Bits/sample : ";
00460 if (flags & FLAG_ULAW)
00461 {
00462 cout << "8 (u-law)" << endl;
00463 }
00464 else
00465 {
00466 cout << dec << myEmuConfig.bitsPerSample << endl;
00467 }
00468 cout << "Channels : " << ((myEmuConfig.channels == SIDEMU_MONO) ? "Mono" : "Stereo") << endl;
00469
00470 myTune.setInfo( mySidInfo );
00471
00472 if ( !sidEmuInitializeSong(myEmuEngine,myTune,selectedSong) )
00473 {
00474 cerr << "ERROR: SID Emulator Engine components not ready" << endl;
00475 exit(EXIT_ERROR_STATUS);
00476 }
00477 myTune.returnInfo( mySidInfo );
00478 if ( !myTune )
00479 {
00480 cerr << mySidInfo.statusString;
00481 exit(EXIT_ERROR_STATUS);
00482 }
00483 cout << "Setting song : " << mySidInfo.currentSong
00484 << " out of " << mySidInfo.songs
00485 << " (default = " << mySidInfo.startSong << ')' << endl;
00486 cout << "Song speed : " << mySidInfo.speedString << endl;
00487
00488 cout << "WAV length : " << seconds << " second";
00489 if ( seconds > 1 )
00490 {
00491 cout << 's';
00492 }
00493 cout << endl;
00494
00495
00496 ofstream tofile( outpathname, ios::out | ios::bin | ios::trunc | ios::noreplace );
00497 if ( !tofile )
00498 {
00499 cerr << "ERROR: Cannot create output file " << "'" << outpathname << "', "
00500 << "probably already exits" << endl;
00501 exit(EXIT_ERROR_STATUS);
00502 }
00503 cout << "Output file : " << outpathname << endl;
00504
00505 udword samplebuffersize;
00506 udword datalength;
00507 uword headersize;
00508
00509 if (flags & FLAG_ULAW)
00510 {
00511 datalength = seconds * myEmuConfig.frequency;
00512 #if defined(IS_LITTLE_ENDIAN)
00513 my_au_hdr.length = convertEndianess (datalength);
00514 #else
00515 my_au_hdr.length = datalength;
00516 #endif
00517 samplebuffersize = myEmuConfig.frequency * 2;
00518 headersize = sizeof(au_hdr);
00519 tofile.write( &my_au_hdr, headersize );
00520 }
00521 else
00522 {
00523 udword bytesPerSample = myEmuConfig.channels*myEmuConfig.bitsPerSample/8;
00524 udword bytesPerSecond = myEmuConfig.frequency*bytesPerSample;
00525 datalength = seconds * bytesPerSecond;
00526 samplebuffersize = bytesPerSecond;
00527 headersize = sizeof(wav_hdr);
00528 #if defined (IS_LITTLE_ENDIAN)
00529 my_wav_hdr.bitspersmpl = myEmuConfig.bitsPerSample;
00530 my_wav_hdr.bytespersmpl = bytesPerSample;
00531 my_wav_hdr.samplefreq = myEmuConfig.frequency;
00532 my_wav_hdr.modus = myEmuConfig.channels;
00533 my_wav_hdr.bytespersec = bytesPerSecond;
00534 my_wav_hdr.length = datalength + headersize - 8;
00535 my_wav_hdr.data_length = datalength;
00536 #else
00537 my_wav_hdr.bitspersmpl = convertEndianess ((uword)myEmuConfig.bitsPerSample);
00538 my_wav_hdr.bytespersmpl = convertEndianess ((uword)bytesPerSample);
00539 my_wav_hdr.samplefreq = convertEndianess (myEmuConfig.frequency);
00540 my_wav_hdr.modus = convertEndianess ((uword)myEmuConfig.channels);
00541 my_wav_hdr.bytespersec = convertEndianess ((udword)bytesPerSecond);
00542 my_wav_hdr.length = convertEndianess (datalength + headersize - 8);
00543 my_wav_hdr.data_length = convertEndianess (datalength);
00544 #endif
00545 tofile.write( &my_wav_hdr, headersize );
00546 }
00547
00548
00549 ubyte* samplebuffer = new ubyte[samplebuffersize];
00550 if ( samplebuffer == 0 )
00551 {
00552 printtext(ERR_NOT_ENOUGH_MEMORY);
00553 }
00554
00555
00556 if ( seconds == 0 )
00557 {
00558 seconds = 60;
00559 }
00560 if ( seconds < fadein_seconds )
00561 {
00562 fadein_seconds = seconds /2;
00563 }
00564 if ( seconds < fadeout_seconds )
00565 {
00566 fadeout_seconds = seconds /2;
00567 }
00568 if (( fadein_seconds + fadeout_seconds ) > seconds )
00569 {
00570 fadein_seconds = 0;
00571 fadeout_seconds = 0;
00572 }
00573 fadein_currentlevel = 0;
00574 fadelevel = ( fadeout_currentlevel = 128 );
00575 fadein_step = ( fadein_seconds * samplebuffersize / (myEmuConfig.bitsPerSample/8) ) / fadelevel;
00576 fadeout_step = ( fadeout_seconds * samplebuffersize / (myEmuConfig.bitsPerSample/8) ) / fadelevel;
00577 fadeout_count = ( fadein_count = 0 );
00578
00579 cout << endl;
00580 cout << "Generating sample data...don't interrupt !" << endl;
00581
00582 if (beginSeconds > 0)
00583 cout << "Skipping seconds : ";
00584 int skipped = 0;
00585 while (skipped < beginSeconds)
00586 {
00587 sidEmuFillBuffer( myEmuEngine, myTune, samplebuffer, samplebuffersize );
00588 skipped++;
00589
00590 cout << setw(5) << setfill(' ') << skipped << "\b\b\b\b\b" << flush;
00591 };
00592 if (beginSeconds > 0)
00593 cout << endl;
00594
00595 cout << "Length of output file (bytes) : ";
00596
00597 datalength = 0;
00598
00599 for ( int sec = 0; sec < seconds; sec++ )
00600 {
00601 sidEmuFillBuffer( myEmuEngine, myTune, samplebuffer, samplebuffersize );
00602 if ( sec < ( fadein_seconds ))
00603 (*fadein_buffer)( samplebuffer, samplebuffersize );
00604 if ( sec >= ( seconds - fadeout_seconds ))
00605 (*fadeout_buffer)( samplebuffer, samplebuffersize );
00606 if (flags & FLAG_ULAW)
00607 {
00608 buffer2ulaw(samplebuffer, samplebuffersize);
00609 tofile.write( samplebuffer, samplebuffersize / 2 );
00610 }
00611 else
00612 {
00613 #if defined(IS_BIG_ENDIAN)
00614 if (myEmuConfig.bitsPerSample == SIDEMU_16BIT)
00615 {
00616 endianswitch_buffer( samplebuffer, samplebuffersize );
00617 }
00618 #endif
00619 tofile.write( samplebuffer, samplebuffersize );
00620 }
00621
00622
00623 cout << setw(10) << setfill(' ') << ( datalength + headersize) << "\b\b\b\b\b\b\b\b\b\b" << flush;
00624
00625 if (flags & FLAG_ULAW)
00626 datalength += samplebuffersize / 2;
00627 else
00628 datalength += samplebuffersize;
00629 }
00630
00631 cout << setw(10) << setfill(' ') << ( datalength + headersize) << endl;
00632 tofile.close();
00633 delete[] outpathname;
00634 delete[] samplebuffer;
00635
00636 cout << endl << "Please do not forget to give the credits whenever using a waveform created" << endl
00637 << "by this application !" << endl << endl;
00638
00639 return 0;
00640 }
00641
00642
00643 void fadeout_buffer_8( ubyte* samplebuffer, udword samplebuffersize )
00644 {
00645 for ( udword i = 0; i < samplebuffersize; i++ )
00646 {
00647 sbyte sam = (sbyte)( 0x80 ^ *(samplebuffer +i));
00648 sword modsam = sam * fadeout_currentlevel;
00649 modsam /= fadelevel;
00650 sam = (sbyte)modsam;
00651 *(samplebuffer +i) = 0x80 ^ sam;
00652
00653 fadeout_count++;
00654 if ( fadeout_count >= fadeout_step )
00655 {
00656 if ( fadeout_currentlevel > 0 )
00657 {
00658 fadeout_currentlevel--;
00659 }
00660 fadeout_count = 0;
00661 }
00662 }
00663 }
00664
00665 void fadeout_buffer_16( ubyte* samplebuffer, udword samplebuffersize )
00666 {
00667 sword *buf = (sword *)samplebuffer;
00668 samplebuffersize /= 2;
00669 for ( udword i = 0; i < samplebuffersize; i++ )
00670 {
00671 sword sam = *(buf +i);
00672 sdword modsam = sam * fadeout_currentlevel;
00673 modsam /= fadelevel;
00674 sam = (sword)modsam;
00675 *(buf +i) = sam;
00676
00677 fadeout_count++;
00678 if ( fadeout_count >= fadeout_step )
00679 {
00680 if ( fadeout_currentlevel > 0 )
00681 {
00682 fadeout_currentlevel--;
00683 }
00684 fadeout_count = 0;
00685 }
00686 }
00687 }
00688
00689 void fadein_buffer_8( ubyte* samplebuffer, udword samplebuffersize )
00690 {
00691 for ( udword i = 0; i < samplebuffersize; i++ )
00692 {
00693 sbyte sam = (sbyte)( 0x80 ^ *(samplebuffer +i));
00694 sword modsam = sam * fadein_currentlevel;
00695 modsam /= fadelevel;
00696 sam = (sbyte)modsam;
00697 *(samplebuffer +i) = 0x80 ^ sam;
00698
00699 fadein_count++;
00700 if ( fadein_count >= fadein_step )
00701 {
00702 if ( fadein_currentlevel < fadelevel )
00703 {
00704 fadein_currentlevel++;
00705 }
00706 fadein_count = 0;
00707 }
00708 }
00709 }
00710
00711 void fadein_buffer_16( ubyte* samplebuffer, udword samplebuffersize )
00712 {
00713 sword *buf = (sword *)samplebuffer;
00714 samplebuffersize /= 2;
00715 for ( udword i = 0; i < samplebuffersize; i++ )
00716 {
00717 sword sam = *(buf +i);
00718 sdword modsam = sam * fadein_currentlevel;
00719 modsam /= fadelevel;
00720 sam = (sword)modsam;
00721 *(buf +i) = sam;
00722
00723 fadein_count++;
00724 if ( fadein_count >= fadein_step )
00725 {
00726 if ( fadein_currentlevel < fadelevel )
00727 {
00728 fadein_currentlevel++;
00729 }
00730 fadein_count = 0;
00731 }
00732 }
00733 }
00734
00735 void error(char* s1, char* s2 = "")
00736 {
00737 cerr << "ERROR: " << s1 << ' ' << "'" << s2 << "'" << endl;
00738 exit(EXIT_ERROR_STATUS);
00739 }
00740
00741
00742 void printtext(int number)
00743 {
00744 switch (number)
00745 {
00746 case TXT_TITLE:
00747 {
00748 cout << "SID2WAV Synthetic Waveform Generator " << "Portable Version " << s2w_version << "/" << emu_version << endl
00749 << "Copyright (c) 1994-97 All rights reserved." << endl
00750 << "Authors: Michael Schwendt <sidplay@geocities.com>" << endl
00751 << " Adam Lorentzon <d93-alo@nada.kth.se>" << endl
00752 #if defined(__amigaos__)
00753 << "AmigaOS port: <phillwooller@geocities.com>" << endl
00754 #endif
00755 << endl;
00756 break;
00757 }
00758 case ERR_ENDIANESS:
00759 {
00760 cerr << "ERROR: Hardware endianess improperly configured." << endl;
00761 exit(EXIT_ERROR_STATUS);
00762 break;
00763 }
00764 case ERR_ENGINE:
00765 case ERR_NOT_ENOUGH_MEMORY:
00766 {
00767 cerr << "ERROR: Not enough memory" << endl;
00768 exit(EXIT_ERROR_STATUS);
00769 break;
00770 }
00771 case ERR_SYNTAX:
00772 {
00773 #ifdef __MSDOS__
00774 cout << " syntax: sid2wav [-<commands>] <datafile> [outputfile]" << endl
00775 #else
00776 cout << " syntax: sid2wav [-<commands>] <datafile>|- [outputfile]" << endl
00777 #endif
00778 << " commands: -h display this screen" << endl
00779 << " -f<num> set frequency in Hz (default: 22050)" << endl
00780 << " -16 16-bit (default: 8-bit)" << endl
00781 << " -s stereo (default: mono)" << endl
00782 << " -ss enable stereo surround" << endl
00783 << " -u au output (8000Hz mono 8-bit u-law)" << endl
00784 << " -o<num> set song number (default: preset)" << endl
00785 << " -a improve PlaySID compatibility (not recommended)" << endl
00786 << " -a2 bank switching mode (overrides -a)" << endl
00787 << " -nf no SID filter emulation" << endl
00788 << " -n enable NTSC-clock speed for VBI tunes (not recommended)" << endl
00789 << " -m<num> mute voices out of 1,2,3,4 (default: none)" << endl
00790 << " example: -m13 (voice 1 and 3 off)" << endl
00791 << " -t<num> set seconds to play (default: 60)" << endl
00792 << " -b<num> begin <num> seconds into the song (default: 0)" << endl
00793 << " -fin<num> fade-in-time in seconds (default: 0)" << endl
00794 << " -fout<num> fade-out-time in seconds (default: 2)" << endl
00795 << endl;
00796 exit(EXIT_ERROR_STATUS);
00797 break;
00798 }
00799 default:
00800 {
00801 cerr << "ERROR: Internal system error" << endl;
00802 exit(EXIT_ERROR_STATUS);
00803 break;
00804 }
00805 }
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 short seg_end[8] =
00829 {
00830 0xFF, 0x1FF, 0x3FF, 0x7FF,
00831 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
00832 };
00833
00834 int search(int val, short *table, int size)
00835 {
00836 int i;
00837
00838 for (i = 0; i < size; i++)
00839 {
00840 if (val <= *table++)
00841 {
00842 return i;
00843 }
00844 }
00845 return size;
00846 }
00847
00848 const int BIAS = 0x84;
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 unsigned char linear2ulaw(int pcm_val)
00879
00880 {
00881 int mask;
00882 int seg;
00883 unsigned char uval;
00884
00885
00886 if (pcm_val < 0)
00887 {
00888 pcm_val = BIAS - pcm_val;
00889 mask = 0x7F;
00890 }
00891 else
00892 {
00893 pcm_val += BIAS;
00894 mask = 0xFF;
00895 }
00896
00897
00898 seg = search(pcm_val, seg_end, 8);
00899
00900
00901
00902
00903 if (seg >= 8)
00904 {
00905 return 0x7F ^ mask;
00906 }
00907 else
00908 {
00909 uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
00910 return uval ^ mask;
00911 }
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 void buffer2ulaw( ubyte* samplebuffer, udword samplebuffersize )
00934 {
00935 sword *wordbuffer = (sword *) samplebuffer;
00936 udword numsamples = samplebuffersize / 2;
00937 for (udword i = 0; i < numsamples; i++)
00938 {
00939 samplebuffer[i] = linear2ulaw ((~wordbuffer[i]) + 1);
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948 void endianswitch_buffer( ubyte* samplebuffer, udword samplebuffersize )
00949 {
00950 uword *wordbuffer = (uword *) samplebuffer;
00951 udword numsamples = samplebuffersize / 2;
00952 for (udword i = 0; i < numsamples; i++)
00953 {
00954 wordbuffer[i] = convertEndianess (wordbuffer[i]);
00955 }
00956 }