Created new file for music functions. PlayMusic now also supports flac,ogg,mp3.

This commit is contained in:
johns 2002-03-27 01:15:35 +00:00
parent e6d3de3326
commit 6196eb2081
5 changed files with 444 additions and 198 deletions

View file

@ -173,10 +173,6 @@ extern unsigned AllocatedSoundMemory;
extern unsigned CompressedSoundMemory;
#endif
#ifdef USE_SDLCD
/// SDL cdrom device
extern SDL_CD *CDRom;
#endif
#if defined(USE_SDLCD) || defined(USE_LIBCDA)
/// cd play mode, ":off" ":random" or ":all"
extern char *CDMode;
@ -192,6 +188,11 @@ extern int NumCDTracks;
-- Functions
----------------------------------------------------------------------------*/
extern Sample* LoadFlac(const char* name); /// Load a flac file
extern Sample* LoadWav(const char* name); /// Load a wav file
extern Sample* LoadOgg(const char* name); /// Load a ogg file
extern Sample* LoadMp3(const char* name); /// Load a mp3 file
/// Register a sound (can be a simple sound or a group)
extern SoundId RegisterSound(char* file[],unsigned number);

View file

@ -33,7 +33,7 @@ MODULE = sound
HDRS = libcda.h
SRCS = sound.c sound_server.c ccl_sound.c sound_id.c \
SRCS = sound.c sound_server.c ccl_sound.c sound_id.c music.c \
mad.c ogg.c flac.c wav.c unitsound.c libcda.c oss_audio.c sdl_audio.c
OBJS = $(addprefix $(OBJDIR), $(SRCS:.c=.$(OE)))

View file

@ -35,6 +35,7 @@
#if defined(WITH_SOUND) && defined(USE_MAD) // {
#include <stdlib.h>
#include <memory.h>
#include "mad.h"
#include "iolib.h"
@ -50,7 +51,7 @@
typedef struct _my_user_ {
CLFile* File; // File handle
Sample* Sample; // Sample buffer
char Buffer[4096]; // Decoded buffer
unsigned char Buffer[4096]; // Decoded buffer
} MyUser;
/*----------------------------------------------------------------------------
@ -68,6 +69,7 @@ typedef struct _my_user_ {
local enum mad_flow MAD_read(void *user, struct mad_stream *stream)
{
int i;
int l;
CLFile *f;
MyUser *u;
@ -76,13 +78,21 @@ local enum mad_flow MAD_read(void *user, struct mad_stream *stream)
u = (MyUser *) user;
f = u->File;
if ((i = CLread(f, u->Buffer, sizeof(u->Buffer))) != sizeof(u->Buffer)) {
if (!i) {
return MAD_FLOW_STOP;
}
l = 0;
// Copy remaining bytes over
if (stream->next_frame) {
memmove(u->Buffer, stream->next_frame,
l = &u->Buffer[sizeof(u->Buffer)] - stream->next_frame);
}
DebugLevel3Fn("%d bytes\n", i);
mad_stream_buffer(stream, u->Buffer, i);
i = CLread(f, u->Buffer + l, sizeof(u->Buffer) - l);
//if (!(l + i)) {
if (!i) {
return MAD_FLOW_STOP;
}
DebugLevel3Fn("%d bytes\n", l + i);
mad_stream_buffer(stream, u->Buffer, l + i);
return MAD_FLOW_CONTINUE;
}

355
src/sound/music.cpp Normal file
View file

@ -0,0 +1,355 @@
// ___________ _________ _____ __
// \_ _____/______ ____ ____ \_ ___ \____________ _/ ____\/ |_
// | __) \_ __ \_/ __ \_/ __ \/ \ \/\_ __ \__ \\ __\\ __\
// | \ | | \/\ ___/\ ___/\ \____| | \// __ \| | | |
// \___ / |__| \___ >\___ >\______ /|__| (____ /__| |__|
// \/ \/ \/ \/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// FreeCraft - A free fantasy real time strategy game engine
//
/**@name music.c - Background music support */
//
// (c) Copyright 2002 by Lutz Sammer
//
// FreeCraft is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation; only version 2 of the License.
//
// FreeCraft is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Id$
//@{
/*----------------------------------------------------------------------------
-- Includes
----------------------------------------------------------------------------*/
#include <stdio.h>
#include "freecraft.h"
#if defined(WITH_SOUND) // {
#include <stdlib.h>
#include <string.h>
#ifdef USE_LIBMODPLUG
#include "../libmodplug/modplug.h"
#endif
#ifdef USE_LIBCDA
#include "libcda.h"
#endif
#ifdef USE_SDLCD
#include <SDL.h>
#endif
#include "iolib.h"
#include "sound.h"
#include "sound_server.h"
/*----------------------------------------------------------------------------
-- Declaration
----------------------------------------------------------------------------*/
#define SoundFrequency 44100 // sample rate of dsp
/*----------------------------------------------------------------------------
-- Variables
----------------------------------------------------------------------------*/
#ifdef USE_LIBMODPLUG
global ModPlugFile* ModFile; /// Mod file loaded into memory
#endif
#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
global Sample* MusicSample; /// Music samples
global int MusicIndex; /// Music sample index
#endif
#if defined(USE_SDLCD) || defined(USE_LIBCDA)
global char *CDMode = ":off"; /// cd play mode, ":off" ":random" or ":all"
global int CDTrack; /// Current cd track
#endif
#ifdef USE_SDLCD
global SDL_CD *CDRom; /// SDL cdrom device
#endif
#ifdef USE_LIBCDA
global int NumCDTracks; /// Number of tracks on the cd
#endif
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
/**
** Stop the current playing music.
**
** @todo FIXME: Stop the CD-PLAYER.
*/
global void StopMusic(void)
{
if (PlayingMusic) {
PlayingMusic = 0; // Callback!
#ifdef USE_LIBMODPLUG
if (ModFile) {
ModPlug_Unload(ModFile);
ModFile = NULL;
return;
}
#endif
#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
if (MusicSample) {
free(MusicSample);
MusicSample = NULL;
MusicIndex = 0;
return;
}
#endif
}
}
#ifdef USE_LIBMODPLUG
/**
** Load a mod file.
*/
local int LoadMod(const char* name)
{
ModPlug_Settings settings;
CLFile* f;
char* buffer;
int size;
int i;
ModPlug_GetSettings(&settings);
settings.mFrequency=SoundFrequency;
#ifdef USE_LIBMODPLUG32
settings.mBits=32;
#else
settings.mBits=16;
#endif
settings.mLoopCount=0; // Disable looping
ModPlug_SetSettings(&settings);
buffer=malloc(8192);
DebugLevel2Fn("Loading `%s'\n",name);
if( !(f=CLopen(name)) ) {
printf("Can't open file `%s'\n",name);
return 0;
}
size=0;
while( (i=CLread(f,buffer+size,8192))==8192 ) {
size+=8192;
buffer=realloc(buffer,size+8192);
}
size+=i;
buffer=realloc(buffer,size);
DebugLevel3Fn("%d\n",size);
StopMusic(); // stop music before new music
ModFile=ModPlug_Load(buffer,size);
free(buffer);
if( ModFile ) {
DebugLevel0Fn("Started\n");
PlayingMusic=1;
return 1;
}
return 0;
}
#endif
#ifdef USE_SDLCD
/**
** Play music from cdrom.
**
** :all :random :off
**
** @param name Name starting with ":".
*/
local int PlayCDRom(const char* name)
{
// Old mode off, starting cdrom play.
if (!strcmp(CDMode, ":off")) {
if (!strncmp(name, ":", 1)) {
StopMusic(); // stop music before new music
SDL_Init(SDL_INIT_CDROM);
CDRom = SDL_CDOpen(0);
SDL_CDStatus(CDRom);
}
}
// CDPlayer command?
if (!strncmp(name, ":", 1)) {
if (!CDRom) {
fprintf(stderr, "Couldn't open cdrom drive: %s\n", SDL_GetError());
return 1;
}
// if mode is play all tracks
if (!strcmp(name, ":all")) {
CDMode = ":all";
SDL_CDPlayTracks(CDRom, 0, 0, 0, 0);
return 1;
}
// if mode is play random tracks
if (!strcmp(name, ":random")) {
CDMode = ":random";
CDTrack = MyRand() % CDRom->numtracks;
SDL_CDPlayTracks(CDRom, CDTrack, 0, 0, 0);
}
CDMode = ":off";
return 1;
}
// FIXME: no cdrom, must stop it now!
return 0;
}
#endif
#ifdef USE_LIBCDA
/**
** Play music from cdrom.
**
** :all :random :off
**
** @param name Name starting with ":".
*/
local int PlayCDRom(const char* name)
{
if (!strcmp(CDMode, ":off")) {
if (!strncmp(name, ":", 1)) {
if (cd_init() < 0) {
fprintf(stderr, "Error initialising libcda \n");
return 1;
}
cd_get_tracks(&CDTrack, &NumCDTracks);
if (NumCDTracks == 0) {
return 1;
}
--CDTrack;
}
}
if (!strncmp(name, ":", 1)) {
// if mode is play all tracks
if (!strcmp(name, ":all")) {
CDMode = ":all";
do {
if (CDTrack > NumCDTracks)
CDTrack = 1;
} while (cd_is_audio(++CDTrack) < 1);
cd_play(CDTrack);
return 1;
}
// if mode is play random tracks
if (!strcmp(name, ":random")) {
CDMode = ":random";
do {
CDTrack = MyRand() % NumCDTracks;
} while (cd_is_audio(CDTrack) < 1);
cd_play(CDTrack);
return 1;
}
CDMode = ":off";
return 1;
}
// FIXME: no cdrom, must stop it now!
return 0;
}
#endif
/**
** Play a music file.
** Currently supported are .mod, .it, .s3m, .wav, .xm.
** Optional .ogg, mp3 and cdrom.
**
** Some quick hacks for mods.
**
** @param name Name of sound file, format is automatic detected.
** Names starting with ':' control the cdrom.
*/
global void PlayMusic(const char* name)
{
char buffer[1024];
Sample *sample;
#ifdef USE_SDLCD
if (PlayCDRom(name)) {
return;
}
#endif
#ifdef USE_LIBCDA
if (PlayCDRom(name)) {
return;
}
#endif
name = LibraryFileName(name, buffer);
#ifdef USE_OGG
if ((sample = LoadOgg(name))) {
if( sample->Channels!=2
|| sample->SampleSize!=16
|| sample->Frequency!=SoundFrequency ) {
DebugLevel0Fn("Not supported music format\n");
free(sample);
return;
}
StopMusic();
MusicSample = sample;
MusicIndex = 0;
PlayingMusic = 1;
return;
}
#endif
#ifdef USE_MAD
if ((sample = LoadMp3(name))) {
if( sample->Channels!=2
|| sample->SampleSize!=16
|| sample->Frequency!=SoundFrequency ) {
DebugLevel0Fn("Not supported music format\n");
free(sample);
return;
}
StopMusic();
MusicSample = sample;
MusicIndex = 0;
PlayingMusic = 1;
return;
}
#endif
#ifdef USE_FLAC
if ((sample = LoadFlac(name))) {
if( sample->Channels!=2
|| sample->SampleSize!=16
|| sample->Frequency!=SoundFrequency ) {
DebugLevel0Fn("Not supported music format\n");
free(sample);
return;
}
StopMusic();
MusicSample = sample;
MusicIndex = 0;
PlayingMusic = 1;
return;
}
#endif
#ifdef USE_LIBMODPLUG
if (LoadMod(name)) {
return;
}
#endif
}
#endif // } WITH_SOUND
//@}

View file

@ -93,11 +93,6 @@
#include <SDL.h>
#endif
extern Sample* LoadFlac(const char* name); /// Load a flac file
extern Sample* LoadWav(const char* name); /// Load a wav file
extern Sample* LoadOgg(const char* name); /// Load a ogg file
extern Sample* LoadMp3(const char* name); /// Load a mp3 file
/*----------------------------------------------------------------------------
-- Defines
----------------------------------------------------------------------------*/
@ -141,165 +136,21 @@ global int WithSoundThread; /// FIXME: docu
global int SoundThreadRunning; /// FIXME: docu
#ifdef USE_SDLCD
global SDL_CD *CDRom;
#endif
#if defined(USE_SDLCD) || defined(USE_LIBCDA)
global char *CDMode = ":off";
global int CDTrack;
#endif
#ifdef USE_LIBCDA
global int NumCDTracks;
global SDL_CD *CDRom; /// SDL cdrom device
#endif
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
#ifdef USE_LIBMODPLUG
local ModPlugFile* ModFile; /// Mod file loaded into memory
/**
** Play a music file. Currently supported are .mod, .it, .s3m, .wav, .xm.
**
** Some quick hacks for mods.
**
** @param name Name of sound file, format is automatic detected.
*/
global void PlayMusic(const char* name)
{
ModPlug_Settings settings;
CLFile* f;
char* buffer;
int size;
int i;
ModPlug_GetSettings(&settings);
settings.mFrequency=SoundFrequency;
#ifdef USE_LIBMODPLUG32
settings.mBits=32;
#else
settings.mBits=16;
#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
extern Sample* MusicSample; /// Music samples
extern int MusicIndex; /// Music sample index
#endif
settings.mLoopCount=0; // Disable looping
ModPlug_SetSettings(&settings);
#ifdef USE_SDLCD
if (!strcmp(CDMode,":off")) {
if (!strncmp(name,":",1)) {
SDL_Init(SDL_INIT_CDROM);
CDRom = SDL_CDOpen(0);
SDL_CDStatus(CDRom);
}
}
if (!strncmp(name,":",1)) {
if (!CDRom) {
fprintf(stderr, "Couldn't open cdrom drive: %s\n", SDL_GetError());
return;
}
#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD) || defined(USE_LIBMODPLUG)
// if mode is play all tracks
if (!strcmp(name, ":all")) {
CDMode = ":all";
SDL_CDPlayTracks(CDRom, 0, 0, 0, 0);
return;
}
// if mode is play random tracks
if (!strcmp(name, ":random")) {
CDMode = ":random";
CDTrack = MyRand() % CDRom->numtracks;
SDL_CDPlayTracks(CDRom, CDTrack, 0, 0, 0);
return;
}
return;
}
#endif
#ifdef USE_LIBCDA
if (!strcmp(CDMode,":off")) {
if (!strncmp(name,":",1)) {
if (cd_init() < 0) {
fprintf(stderr,"Error initialising libcda \n");
return;
}
cd_get_tracks(&CDTrack, &NumCDTracks);
if (NumCDTracks == 0)
return;
--CDTrack;
}
}
if (!strncmp(name,":",1)) {
// if mode is play all tracks
if (!strcmp(name, ":all")) {
CDMode = ":all";
do {
if (CDTrack > NumCDTracks)
CDTrack = 1;
} while (cd_is_audio(++CDTrack) < 1);
cd_play(CDTrack);
return;
}
// if mode is play random tracks
if (!strcmp(name, ":random")) {
CDMode = ":random";
do {
CDTrack = MyRand() % NumCDTracks;
} while (cd_is_audio(CDTrack) < 1);
cd_play(CDTrack);
return;
}
}
#endif
buffer=malloc(8192);
name=LibraryFileName(name,buffer);
DebugLevel2Fn("Loading `%s'\n",name);
if( !(f=CLopen(name)) ) {
printf("Can't open file `%s'\n",name);
return;
}
size=0;
while( (i=CLread(f,buffer+size,8192))==8192 ) {
size+=8192;
buffer=realloc(buffer,size+8192);
}
size+=i;
buffer=realloc(buffer,size);
DebugLevel0Fn("%d\n",size);
StopMusic(); // stop music before new music
ModFile=ModPlug_Load(buffer,size);
free(buffer);
if( ModFile ) {
DebugLevel0Fn("Started\n");
PlayingMusic=1;
}
}
/**
** Stop the current playing music.
*/
global void StopMusic(void)
{
if( PlayingMusic ) {
PlayingMusic=0; // Callback!
if( ModFile ) {
ModPlug_Unload(ModFile);
ModFile=NULL;
}
}
}
extern ModPlugFile* ModFile; /// Mod file loaded into memory
/**
** Mix music to stereo 32 bit.
@ -307,49 +158,72 @@ global void StopMusic(void)
** @param buffer Buffer for mixed samples.
** @param size Number of samples that fits into buffer.
*/
local void MixMusicToStereo32(int* buffer,int size)
local void MixMusicToStereo32(int* buffer, int size)
{
#ifdef USE_LIBMODPLUG32
long* buf;
#else
short* buf;
#endif
int i;
int n;
if( PlayingMusic ) {
DebugCheck( !ModFile );
buf=alloca(size*sizeof(*buf));
n=ModPlug_Read(ModFile,buf,size*sizeof(*buf));
for( i=0; i<n/sizeof(*buf); ++i ) { // Add to our samples
if (PlayingMusic) {
n = 0;
#ifdef USE_LIBMODPLUG
if (ModFile) {
#ifdef USE_LIBMODPLUG32
buffer[i]+=((buf[i]>>16)*MusicVolume)/256;
long *buf;
#else
buffer[i]+=(buf[i]*MusicVolume)/256;
short *buf;
#endif
}
buf = alloca(size * sizeof(*buf));
if( n!=size*sizeof(*buf) ) { // End reached
SCM cb;
n = ModPlug_Read(ModFile, buf, size * sizeof(*buf));
DebugLevel2Fn("End of music %d\n",i);
PlayingMusic=0;
if( ModFile ) {
ModPlug_Unload(ModFile);
for (i = 0; i < n / sizeof(*buf); ++i) { // Add to our samples
#ifdef USE_LIBMODPLUG32
buffer[i] += ((buf[i] >> 16) * MusicVolume) / 256;
#else
buffer[i] += (buf[i] * MusicVolume) / 256;
#endif
}
if( CallbackMusic ) {
cb=gh_symbol2scm("music-stopped");
if( !gh_null_p(symbol_boundp(cb,NIL)) ) {
n = n != size * sizeof(*buf); // End reached?
}
#endif
#if defined(USE_OGG) || defined(USE_FLAC) || defined(USE_MAD)
if (MusicSample) {
short *buf;
buf = (short *)(MusicSample->Data + MusicIndex);
if (size * 2 > MusicSample->Length - MusicIndex) {
n = MusicSample->Length - MusicIndex;
} else {
n = size * 2;
}
n >>= 1;
for (i = 0; i < n; ++i) { // Add to our samples
buffer[i] += (buf[i] * MusicVolume) / 256;
}
MusicIndex += i * 2;
n = MusicIndex == MusicSample->Length;
}
#endif
if (n) { // End reached
SCM cb;
DebugLevel3Fn("End of music %d\n", i);
PlayingMusic = 0;
if (ModFile) {
ModPlug_Unload(ModFile);
}
// FIXME: we are inside the SDL callback!
if (CallbackMusic) {
cb = gh_symbol2scm("music-stopped");
if (!gh_null_p(symbol_boundp(cb, NIL))) {
SCM value;
value=symbol_value(cb,NIL);
if( !gh_null_p(value) ) {
gh_apply(value,NIL);
value = symbol_value(cb, NIL);
if (!gh_null_p(value)) {
gh_apply(value, NIL);
}
}
}
@ -371,6 +245,11 @@ global void StopMusic(void)
#endif
/**
** Check cdrom.
**
** Perodic called from the main loop.
*/
global void CDRomCheck(void)
{
#ifdef USE_SDLCD
@ -394,8 +273,9 @@ global void CDRomCheck(void)
} else {
DebugLevel0Fn("get track\n");
CDTrack = cd_current_track() + 1;
if (CDTrack > NumCDTracks)
if (CDTrack > NumCDTracks) {
CDTrack = 1;
}
}
#endif
}