Ticket #8108: ogg.diff
File ogg.diff, 17.6 KB (added by , 22 years ago) |
---|
-
Makefile
? config.h ? ogg.diff RCS file: /cvsroot/scummvm/scummvm/Makefile,v retrieving revision 1.16 diff -u -r1.16 Makefile
36 36 # DEFINES += -DDUMP_SCRIPTS 37 37 38 38 # Uncomment this to activate the MAD lib for compressed sound files 39 DEFINES += -D COMPRESSED_SOUND_FILE39 DEFINES += -DUSE_MAD 40 40 LIBS += -lmad 41 42 # Uncomment this to activate the Ogg Vorbis lib for compressed sound files 43 DEFINES += -DUSE_VORBIS 44 LIBS += -lvorbisfile -lvorbis 41 45 42 46 # Uncomment this to activate the ALSA lib for midi 43 47 # DEFINES += -DUSE_ALSA -
common/scummsys.h
RCS file: /cvsroot/scummvm/scummvm/common/scummsys.h,v retrieving revision 1.6 diff -u -r1.6 scummsys.h
31 31 const bool true(1), false(0); 32 32 #endif /* HAVE_NO_BOOL */ 33 33 34 #if defined(USE_MAD) || defined(USE_VORBIS) 35 #define COMPRESSED_SOUND_FILE 36 #endif 37 34 38 #if defined(_MSC_VER) 35 39 36 40 //#pragma warning (disable: 4244) -
scumm/sound.cpp
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.cpp,v retrieving revision 1.42 diff -u -r1.42 sound.cpp
738 738 int rate, comp; 739 739 byte *data; 740 740 741 #ifdef COMPRESSED_SOUND_FILE741 #ifdef USE_MAD 742 742 if (file_size > 0) { 743 743 data = (byte *)calloc(file_size + MAD_BUFFER_GUARD, 1); 744 744 … … 1116 1116 } 1117 1117 1118 1118 int Sound::playSfxSound_MP3(void *sound, uint32 size) { 1119 #ifdef COMPRESSED_SOUND_FILE1119 #ifdef USE_MAD 1120 1120 if (_soundsPaused) 1121 1121 return -1; 1122 1122 return _scumm->_mixer->playMP3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE); … … 1219 1219 char track_name[1024]; 1220 1220 File * file = new File(); 1221 1221 int current_index; 1222 struct mad_stream stream;1223 struct mad_frame frame;1224 unsigned char buffer[8192];1225 unsigned int buflen = 0;1226 int count = 0;1227 1222 1228 1223 // See if we find the track in the cache 1229 1224 for (i = 0; i < CACHE_TRACKS; i++) 1230 1225 if (_cached_tracks[i] == track) { 1231 if (_ mp3_tracks[i])1226 if (_track_info[i]) 1232 1227 return i; 1233 1228 else 1234 1229 return -1; … … 1237 1232 _current_cache %= CACHE_TRACKS; 1238 1233 1239 1234 // Not found, see if it exists 1235 1236 // First, delete the previous track info object 1237 delete _track_info[current_index]; 1238 _track_info[current_index] = NULL; 1239 1240 _cached_tracks[current_index] = track; 1241 1242 #ifdef USE_MAD 1240 1243 sprintf(track_name, "track%d.mp3", track); 1241 1244 file->open(track_name, _scumm->getGameDataPath()); 1242 _cached_tracks[current_index] = track;1243 1245 1244 /* First, close the previous file */ 1245 if (_mp3_tracks[current_index]) 1246 _mp3_tracks[current_index]->close(); 1247 1248 _mp3_tracks[current_index] = NULL; 1249 if (file->isOpen() == false) { 1250 // This warning is pretty pointless. 1251 debug(1, "Track %d not available in mp3 format", track); 1246 if (file->isOpen()) { 1247 _track_info[current_index] = new MP3TrackInfo(file); 1248 if (_track_info[current_index]->error()) { 1249 delete _track_info[current_index]; 1250 _track_info[current_index] = NULL; 1251 return -1; 1252 } 1253 return current_index; 1254 } 1255 #endif 1256 1257 #ifdef USE_VORBIS 1258 sprintf(track_name, "track%d.ogg", track); 1259 file->open(track_name, _scumm->getGameDataPath()); 1260 1261 if (file->isOpen()) { 1262 _track_info[current_index] = new VorbisTrackInfo(file); 1263 if (_track_info[current_index]->error()) { 1264 delete _track_info[current_index]; 1265 _track_info[current_index] = NULL; 1266 return -1; 1267 } 1268 return current_index; 1269 } 1270 #endif 1271 1272 debug(1, "Track %d not available in compressed format", track); 1273 return -1; 1274 } 1275 1276 int Sound::playMP3CDTrack(int track, int num_loops, int start, int delay) { 1277 int index; 1278 _scumm->_vars[_scumm->VAR_MI1_TIMER] = 0; 1279 1280 if (_soundsPaused) 1281 return 0; 1282 1283 if ((num_loops == 0) && (start == 0)) { 1284 return 0; 1285 } 1286 1287 index = getCachedTrack(track); 1288 if (index < 0) 1289 return -1; 1290 1291 if (_dig_cd_playing) 1292 _scumm->_mixer->stop(_dig_cd_index); 1293 _dig_cd_index = _track_info[index]->play(_scumm->_mixer, start, delay); 1294 _dig_cd_playing = true; 1295 _dig_cd_track = track; 1296 _dig_cd_num_loops = num_loops; 1297 _dig_cd_start = start; 1298 _dig_cd_delay = delay; 1299 return 0; 1300 } 1301 1302 int Sound::stopMP3CD() { 1303 if (_dig_cd_playing == true) { 1304 _scumm->_mixer->stop(_dig_cd_index); 1305 _dig_cd_playing = false; 1306 _dig_cd_track = 0; 1307 _dig_cd_num_loops = 0; 1308 _dig_cd_start = 0; 1309 _dig_cd_delay = 0; 1310 return 0; 1311 } 1312 return -1; 1313 } 1314 1315 int Sound::pollMP3CD() { 1316 if (_dig_cd_playing == true) 1317 return 1; 1318 return 0; 1319 } 1320 1321 int Sound::updateMP3CD() { 1322 if (_dig_cd_playing == false) 1323 return -1; 1324 1325 if (_scumm->_mixer->_channels[_dig_cd_index] == NULL) { 1326 warning("Error in MP3 decoding"); 1252 1327 return -1; 1253 1328 } 1254 1329 1330 if (_scumm->_mixer->_channels[_dig_cd_index]->soundFinished()) { 1331 if (_dig_cd_num_loops == -1 || --_dig_cd_num_loops > 0) 1332 playMP3CDTrack(_dig_cd_track, _dig_cd_num_loops, _dig_cd_start, _dig_cd_delay); 1333 else 1334 stopMP3CD(); 1335 } 1336 1337 return 0; 1338 } 1339 1340 #ifdef USE_MAD 1341 Sound::MP3TrackInfo::MP3TrackInfo(File *file) { 1342 struct mad_stream stream; 1343 struct mad_frame frame; 1344 unsigned char buffer[8192]; 1345 unsigned int buflen = 0; 1346 int count = 0; 1347 1255 1348 // Check the format and bitrate 1256 1349 mad_stream_init(&stream); 1257 1350 mad_frame_init(&frame); … … 1263 1356 bytes = file->read(buffer + buflen, sizeof(buffer) - buflen); 1264 1357 if (bytes <= 0) { 1265 1358 if (bytes == -1) { 1266 warning("Invalid f ormat for track %d", track);1359 warning("Invalid file format"); 1267 1360 goto error; 1268 1361 } 1269 1362 break; … … 1295 1388 } 1296 1389 1297 1390 if (count) 1298 memcpy(&_mad_header [current_index], &frame.header, sizeof(mad_header));1391 memcpy(&_mad_header, &frame.header, sizeof(mad_header)); 1299 1392 else { 1300 warning("Invalid f ormat for track %d", track);1393 warning("Invalid file format"); 1301 1394 goto error; 1302 1395 } 1303 1396 1304 1397 mad_frame_finish(&frame); 1305 1398 mad_stream_finish(&stream); 1306 1399 // Get file size 1307 _ mp3_size[current_index]= file->size();1308 _ mp3_tracks[current_index]= file;1309 1310 return current_index;1400 _size = file->size(); 1401 _file = file; 1402 _error_flag = false; 1403 return; 1311 1404 1312 1405 error: 1313 1406 mad_frame_finish(&frame); 1314 1407 mad_stream_finish(&stream); 1408 _error_flag = true; 1315 1409 delete file; 1316 1317 return -1;1318 1410 } 1319 1411 1320 int Sound::playMP3CDTrack(int track, int num_loops, int start, int delay) { 1321 int index; 1412 int Sound::MP3TrackInfo::play(SoundMixer *mixer, int start, int delay) { 1322 1413 unsigned int offset; 1323 1414 mad_timer_t duration; 1324 _scumm->_vars[_scumm->VAR_MI1_TIMER] = 0;1325 1326 if (_soundsPaused)1327 return 0;1328 1329 if ((num_loops == 0) && (start == 0)) {1330 return 0;1331 }1332 1333 index = getCachedTrack(track);1334 if (index < 0)1335 return -1;1336 1415 1337 1416 // Calc offset. As all bitrates are in kilobit per seconds, the division by 200 is always exact 1338 offset = (start * (_mad_header [index].bitrate / (8 * 25))) / 3;1417 offset = (start * (_mad_header.bitrate / (8 * 25))) / 3; 1339 1418 1340 1419 // Calc delay 1341 1420 if (!delay) { 1342 mad_timer_set(&duration, (_ mp3_size[index] * 8) / _mad_header[index].bitrate,1343 (_ mp3_size[index] * 8) % _mad_header[index].bitrate, _mad_header[index].bitrate);1421 mad_timer_set(&duration, (_size * 8) / _mad_header.bitrate, 1422 (_size * 8) % _mad_header.bitrate, _mad_header.bitrate); 1344 1423 } else { 1345 1424 mad_timer_set(&duration, delay / 75, delay % 75, 75); 1346 1425 } 1347 1426 1348 1427 // Go 1349 _ mp3_tracks[index]->seek(offset, SEEK_SET);1428 _file->seek(offset, SEEK_SET); 1350 1429 1351 if (_mp3_cd_playing == true) 1352 _scumm->_mixer->stop(_mp3_index); 1353 _mp3_index = _scumm->_mixer->playMP3CDTrack(NULL, _mp3_tracks[index], duration); 1354 _mp3_cd_playing = true; 1355 _mp3_cd_track = track; 1356 _mp3_cd_num_loops = num_loops; 1357 _mp3_cd_start = start; 1358 _mp3_cd_delay = delay; 1359 return 0; 1430 return mixer->playMP3CDTrack(NULL, _file, duration); 1360 1431 } 1361 1432 1362 int Sound::stopMP3CD() { 1363 if (_mp3_cd_playing == true) { 1364 _scumm->_mixer->stop(_mp3_index); 1365 _mp3_cd_playing = false; 1366 _mp3_cd_track = 0; 1367 _mp3_cd_num_loops = 0; 1368 _mp3_cd_start = 0; 1369 _mp3_cd_delay = 0; 1370 return 0; 1433 Sound::MP3TrackInfo::~MP3TrackInfo() { 1434 if (! _error_flag) 1435 _file->close(); 1436 } 1437 1438 #endif 1439 1440 #ifdef USE_VORBIS 1441 // These are wrapper functions to allow using a File object to 1442 // provide data to the OggVorbis_File object. 1443 1444 struct file_info { 1445 File *file; 1446 int start, curr_pos; 1447 size_t len; 1448 }; 1449 1450 static size_t read_wrap(void *ptr, size_t size, size_t nmemb, void *datasource) { 1451 file_info *f = (file_info *) datasource; 1452 int result; 1453 1454 nmemb *= size; 1455 if (f->curr_pos > (int) f->len) 1456 nmemb = 0; 1457 else if (nmemb > f->len - f->curr_pos) 1458 nmemb = f->len - f->curr_pos; 1459 result = f->file->read(ptr, nmemb); 1460 if (result == -1) { 1461 f->curr_pos = f->file->pos() - f->start; 1462 return (size_t) -1; 1463 } 1464 else { 1465 f->curr_pos += result; 1466 return result / size; 1371 1467 } 1372 return -1;1373 1468 } 1374 1469 1375 int Sound::pollMP3CD() { 1376 if (_mp3_cd_playing == true) 1377 return 1; 1470 static int seek_wrap(void *datasource, ogg_int64_t offset, int whence) { 1471 file_info *f = (file_info *) datasource; 1472 1473 if (whence == SEEK_SET) 1474 offset += f->start; 1475 else if (whence == SEEK_END) { 1476 offset += f->start + f->len; 1477 whence = SEEK_SET; 1478 } 1479 1480 f->file->seek(offset, whence); 1481 f->curr_pos = f->file->pos() - f->start; 1482 return f->curr_pos; 1483 } 1484 1485 static int close_wrap(void *datasource) { 1486 file_info *f = (file_info *) datasource; 1487 1488 f->file->close(); 1489 delete f; 1378 1490 return 0; 1379 1491 } 1380 1492 1381 int Sound::updateMP3CD() { 1382 if (_mp3_cd_playing == false) 1383 return -1; 1493 static long tell_wrap(void *datasource) { 1494 file_info *f = (file_info *) datasource; 1384 1495 1385 if (_scumm->_mixer->_channels[_mp3_index] == NULL) { 1386 warning("Error in MP3 decoding"); 1387 return -1; 1496 return f->file->pos(); 1497 } 1498 1499 static ov_callbacks File_wrap = { 1500 read_wrap, seek_wrap, close_wrap, tell_wrap 1501 }; 1502 1503 Sound::VorbisTrackInfo::VorbisTrackInfo(File *file) { 1504 file_info *f = new file_info; 1505 1506 f->file = file; 1507 f->start = 0; 1508 f->len = file->size(); 1509 f->curr_pos = file->pos(); 1510 1511 if (ov_open_callbacks((void *) f, &_ov_file, NULL, 0, File_wrap) < 0) { 1512 warning("Invalid file format"); 1513 _error_flag = true; 1514 delete f; 1515 delete file; 1388 1516 } 1517 else { 1518 _error_flag = false; 1519 _file = file; 1389 1520 1390 if (_scumm->_mixer->_channels[_mp3_index]->soundFinished()) { 1391 if (_mp3_cd_num_loops == -1 || --_mp3_cd_num_loops > 0) 1392 playMP3CDTrack(_mp3_cd_track, _mp3_cd_num_loops, _mp3_cd_start, _mp3_cd_delay); 1393 else 1394 stopMP3CD(); 1521 // Check the file format 1522 if (ov_info(&_ov_file, -1)->rate != 22050) 1523 warning("Vorbis code currently only supports files encoded at 22050 Hz"); 1395 1524 } 1525 } 1396 1526 1397 return 0; 1527 int Sound::VorbisTrackInfo::play(SoundMixer *mixer, int start, int delay) { 1528 ov_time_seek(&_ov_file, start / 75.0); 1529 return mixer->playVorbisCDTrack(NULL, &_ov_file, delay / 75.0); 1530 } 1531 1532 Sound::VorbisTrackInfo::~VorbisTrackInfo() { 1533 if (! _error_flag) { 1534 ov_clear(&_ov_file); 1535 delete _file; 1536 } 1398 1537 } 1538 1539 #endif 1540 1399 1541 #endif -
scumm/sound.h
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.h,v retrieving revision 1.14 diff -u -r1.14 sound.h
65 65 uint16 _mouthSyncTimes[52]; 66 66 uint _curSoundPos; 67 67 68 #ifdef COMPRESSED_SOUND_FILE 68 69 MP3OffsetTable *offset_table; // SO3 MP3 compressed audio 69 70 int num_sound_effects; // SO3 MP3 compressed audio 70 #ifdef COMPRESSED_SOUND_FILE71 71 72 72 #define CACHE_TRACKS 10 73 73 74 74 /* used for mp3 CD music */ 75 75 76 76 int _cached_tracks[CACHE_TRACKS]; 77 struct mad_header _mad_header[CACHE_TRACKS]; 78 long _mp3_size[CACHE_TRACKS]; 79 File *_mp3_tracks[CACHE_TRACKS]; 80 int _mp3_index; 81 int _mp3_cd_track; 82 int _mp3_cd_start; 83 int _mp3_cd_delay; 84 int _mp3_cd_num_loops; 85 bool _mp3_cd_playing; 77 int _dig_cd_index; 78 int _dig_cd_track; 79 int _dig_cd_start; 80 int _dig_cd_delay; 81 int _dig_cd_num_loops; 82 bool _dig_cd_playing; 83 84 class DigitalTrackInfo { 85 public: 86 virtual bool error() = 0; 87 virtual int play(SoundMixer *mixer, int start, int delay) = 0; 88 virtual ~DigitalTrackInfo() { } 89 }; 90 91 DigitalTrackInfo *_track_info[CACHE_TRACKS]; 92 93 #ifdef USE_MAD 94 class MP3TrackInfo : public DigitalTrackInfo { 95 private: 96 struct mad_header _mad_header; 97 long _size; 98 File *_file; 99 bool _error_flag; 100 101 public: 102 MP3TrackInfo(File *file); 103 ~MP3TrackInfo(); 104 bool error() { return _error_flag; } 105 int play(SoundMixer *mixer, int start, int delay); 106 }; 107 #endif 108 109 #ifdef USE_VORBIS 110 class VorbisTrackInfo : public DigitalTrackInfo { 111 private: 112 File *_file; 113 OggVorbis_File _ov_file; 114 bool _error_flag; 115 116 public: 117 VorbisTrackInfo(File *file); 118 ~VorbisTrackInfo(); 119 bool error() { return _error_flag; } 120 int play(SoundMixer *mixer, int start, int delay); 121 }; 122 #endif 123 86 124 #endif 87 125 88 126 Scumm * _scumm; -
sound/mixer.cpp
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.cpp,v retrieving revision 1.20 diff -u -r1.20 mixer.cpp
120 120 _beginSlots = index; 121 121 } 122 122 123 #ifdef COMPRESSED_SOUND_FILE123 #ifdef USE_MAD 124 124 int SoundMixer::playMP3(PlayingSoundHandle * handle, void *sound, uint32 size, byte flags) { 125 125 for (int i = _beginSlots; i != NUM_CHANNELS; i++) { 126 126 if (_channels[i] == NULL) { … … 144 144 } 145 145 #endif 146 146 147 #ifdef USE_VORBIS 148 int SoundMixer::playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration) { 149 for (int i = _beginSlots; i != NUM_CHANNELS; i++) { 150 if (_channels[i] == NULL) { 151 return insertAt(handle, i, new ChannelVorbis(this, ov_file, duration)); 152 } 153 } 154 155 warning("SoundMixer::out of mixer slots"); 156 return -1; 157 } 158 #endif 159 147 160 void SoundMixer::mix(int16 *buf, uint len) { 148 161 if (_paused) { 149 162 memset(buf, 0, 2 * len * sizeof(int16)); … … 713 726 delete this; 714 727 } 715 728 716 #ifdef COMPRESSED_SOUND_FILE729 #ifdef USE_MAD 717 730 SoundMixer::ChannelMP3::ChannelMP3(SoundMixer * mixer, void * sound, uint size, byte flags) { 718 731 _mixer = mixer; 719 732 _flags = flags; … … 959 972 mad_stream_finish(&_stream); 960 973 961 974 delete this; 975 } 976 977 #endif 978 979 #ifdef USE_VORBIS 980 SoundMixer::ChannelVorbis::ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration) { 981 _mixer = mixer; 982 _ov_file = ov_file; 983 984 if (duration) 985 _end_pos = ov_time_tell(ov_file) + duration; 986 else 987 _end_pos = 0; 988 989 _eof_flag = false; 990 _toBeDestroyed = false; 991 } 992 993 void SoundMixer::ChannelVorbis::mix(int16 * data, uint len) { 994 if (_toBeDestroyed) { 995 realDestroy(); 996 return; 997 } 998 999 if (_eof_flag) { 1000 memset(data, 0, sizeof(int16) * 2 * len); 1001 return; 1002 } 1003 1004 int channels = ov_info(_ov_file, -1)->channels; 1005 uint len_left = len * channels * 2; 1006 int16 *samples = new int16[len_left / 2]; 1007 char *read_pos = (char *) samples; 1008 int volume = _mixer->_musicVolume; 1009 1010 // Read the samples 1011 while (len_left > 0) { 1012 long result = ov_read(_ov_file, read_pos, len_left, 1013 #ifdef SCUMM_BIG_ENDIAN 1014 1, 1015 #else 1016 0, 1017 #endif 1018 2, 1, NULL); 1019 if (result == 0) { 1020 _eof_flag = true; 1021 memset(read_pos, 0, len_left); 1022 break; 1023 } 1024 else if (result < 0) { 1025 debug(1, "Decode error %d in Vorbis file", result); 1026 // Don't delete it yet, that causes problems in 1027 // the CD player emulation code. 1028 _eof_flag = true; 1029 memset(read_pos, 0, len_left); 1030 break; 1031 } 1032 else { 1033 len_left -= result; 1034 read_pos += result; 1035 } 1036 } 1037 1038 // Mix the samples in 1039 for (uint i = 0; i < len; i++) { 1040 int16 sample = (int16) ((int32) samples[i * channels] * volume / 128); 1041 *data++ += sample; 1042 if (channels > 1) 1043 sample = (int16) ((int32) samples[i * channels + 1] * volume / 128); 1044 *data++ += sample; 1045 } 1046 1047 delete [] samples; 1048 } 1049 1050 void SoundMixer::ChannelVorbis::realDestroy() { 1051 _mixer->unInsert(this); 1052 delete this; 1053 } 1054 1055 bool SoundMixer::ChannelVorbis::soundFinished() { 1056 return _eof_flag || (_end_pos > 0 && 1057 ov_time_tell(_ov_file) >= _end_pos); 962 1058 } 963 1059 964 1060 #endif -
sound/mixer.h
RCS file: /cvsroot/scummvm/scummvm/sound/mixer.h,v retrieving revision 1.10 diff -u -r1.10 mixer.h
25 25 26 26 #include <stdio.h> 27 27 28 #ifdef COMPRESSED_SOUND_FILE28 #ifdef USE_MAD 29 29 #include <mad.h> 30 30 #endif 31 31 32 #ifdef USE_VORBIS 33 #include <vorbis/vorbisfile.h> 34 #endif 35 32 36 #include "common/scummsys.h" 33 37 #include "common/system.h" 34 38 … … 92 96 void realDestroy(); 93 97 }; 94 98 95 #ifdef COMPRESSED_SOUND_FILE99 #ifdef USE_MAD 96 100 97 101 class ChannelMP3 : public Channel { 98 102 SoundMixer * _mixer; … … 138 142 139 143 #endif 140 144 145 #ifdef USE_VORBIS 146 class ChannelVorbis : public Channel { 147 SoundMixer * _mixer; 148 OggVorbis_File * _ov_file; 149 double _end_pos; 150 bool _eof_flag; 151 152 public: 153 ChannelVorbis(SoundMixer * mixer, OggVorbis_File * ov_file, double duration); 154 155 void mix(int16 * data, uint len); 156 void realDestroy(); 157 bool soundFinished(); 158 }; 159 #endif 160 141 161 static void onGenerateSamples(void * s, byte * samples, int len); 142 162 143 163 public: … … 187 207 int playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate, byte flags, int id); 188 208 int playStream(PlayingSoundHandle * handle, int index, void * sound, uint32 size, uint rate, 189 209 byte flags, int32 timeout = 3, int32 buffer_size = 2000000); 190 #ifdef COMPRESSED_SOUND_FILE210 #ifdef USE_MAD 191 211 int playMP3(PlayingSoundHandle * handle, void * sound, uint32 size, byte flags); 192 212 int playMP3CDTrack(PlayingSoundHandle * handle, File * file, mad_timer_t duration); 213 #endif 214 #ifdef USE_VORBIS 215 int playVorbisCDTrack(PlayingSoundHandle * handle, OggVorbis_File * ov_file, double duration); 193 216 #endif 194 217 195 218 /* Premix procedure, useful when using fmopl adlib */