* Addition of forgotten HMP-MIDI conversion

* SConstruct fix: unnecessary dependency on said conversion code
* Music playback from internal Descent files
This commit is contained in:
md2211 2006-10-18 17:08:59 +00:00
parent 5d09ba6a23
commit f1706cf2ec
5 changed files with 304 additions and 26 deletions

View file

@ -96,7 +96,6 @@ common_sources = [
'main/gameseq.c',
'main/gauges.c',
'main/hash.c',
'main/hmp2mid.c',
'main/hostage.c',
'main/hud.c',
'main/hudlog.c',
@ -252,15 +251,16 @@ arch_linux_sources = [
'arch/sdl/mouse.c'
]
# choosing a sound implementation for linux
# choosing a sound implementation for Linux
common_sound_hmp2mid = [ 'main/hmp2mid.c' ]
arch_linux_sound_sdlmixer = [ 'arch/sdl/mixdigi.c', 'arch/sdl/mixmusic.c' ]
arch_linux_sound_old = [ 'arch/sdl/digi.c', 'arch/linux/hmiplay.c' ]
if (sdlmixer == 1):
common_sources += common_sound_hmp2mid
arch_linux_sources += arch_linux_sound_sdlmixer
else:
arch_linux_sources += arch_linux_sound_old
# for windows
arch_win32_sources = [
@ -412,6 +412,8 @@ if (shareware == 1):
if (shareware == 0) and (editor == 0):
common_sources = ['main/loadrl2.c'] + common_sources
print '\n'
# finally building program...
env.Program(target=str(target), source = common_sources, LIBS = alllibs, LINKFLAGS = str(lflags))
env.Install(BIN_DIR, str(target))

View file

@ -18,6 +18,7 @@
#include <errno.h>
#include "cfile.h"
#define MIX_MUSIC_DEBUG 1
#define MUSIC_FADE_TIME 500 //milliseconds
#define MUSIC_EXTENSION_ARG "-music_ext"
@ -29,10 +30,10 @@ void music_done() {
current_music = NULL;
}
void convert_hmp(char * filename) {
char *mid_filename = "tmp.mid";
void convert_hmp(char *filename, char *mid_filename) {
if (access(mid_filename, R_OK) != 0) {
if (MIX_MUSIC_DEBUG) printf("convert_hmp: converting %s to %s\n", filename, mid_filename);
const char *err;
CFILE *hmp_in;
@ -62,43 +63,50 @@ void convert_hmp(char * filename) {
return;
}
}
else {
if (MIX_MUSIC_DEBUG) printf("convert_hmp: %s already exists\n", mid_filename);
}
}
void mix_play_music(char *filename, int loop) {
int got_end=0, i, t;
loop *= -1;
loop *= -1;
int i, t, got_end=0;
int fn_buf_len = strlen(DESCENT_DATA_PATH) + strlen(filename) + 16;
char real_filename[fn_buf_len];
char music_file_extension[8] = "mid";
// Quick hack to suppress the .hmp extension
char real_filename[fn_buf_len];
char midi_filename[16];
char music_title[16];
char music_file_extension[8];
// Quick hack to filter out the .hmp extension
for (i=0; !got_end; i++) {
switch (filename[i]) {
case '.':
// prematurely end the string when we find the dot
filename[i] = '\0';
case '\0':
music_title[i] = '\0';
got_end = 1;
break;
default:
music_title[i] = filename[i];
}
}
// What is the extension of external files? If none, default to internal MIDI
t = FindArg(MUSIC_EXTENSION_ARG);
if (t > 0) {
sprintf(music_file_extension,"%.3s", Args[t+1]);
sprintf(music_file_extension, "%.3s", Args[t+1]);
// Building absolute path to the file
sprintf(real_filename, "%s%s.%s", DESCENT_DATA_PATH, music_title, music_file_extension);
}
else {
convert_hmp(filename);
//hmp2mid((hmp2mid_read_func_t)cfread, hmp_in, mid_out);
sprintf(midi_filename, "%s.mid", music_title);
convert_hmp(filename, midi_filename);
// Relative path for now (we're using $HOME/.d1x-rebirth/ as working dir)
strcpy(real_filename, midi_filename);
}
// Building absolute path to the file
sprintf(real_filename, "%s%s.%s", DESCENT_DATA_PATH, filename, music_file_extension);
current_music = Mix_LoadMUS(real_filename);
if (current_music) {
if ((current_music = Mix_LoadMUS(real_filename))) {
printf("Now playing: %s\n", real_filename);
if (Mix_PlayingMusic()) {
// Fade-in effect sounds cleaner if we're already playing something

232
main/hmp2mid.c Normal file
View file

@ -0,0 +1,232 @@
/* hmp 2 midi file conversion. The conversion algorithm is based on the
conversion algorithms found in d1x, d2x-xl and jjffe. The code is mine.
Copyright 2006 Hans de Goede
This file and the acompanying hmp2mid.h file are free software;
you can redistribute them and/or modify them under the terms of the GNU
Library General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
These files are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with these files; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "hmp2mid.h"
/* Some convience macros to keep the code below more readable */
#define HMP_READ(buf, count) \
{\
if (read_func(buf, 1, count, hmp_in) != (count)) \
{ \
free(mid_track_buf); \
return hmp_read_error; \
} \
/* notice that when we are not actually in the track reading code this \
is bogus, but does no harm. And in the track code it helps :) */ \
track_length -= count; \
}
#define HMP_READ_DWORD(dest) \
{ \
unsigned char _buf[4]; \
HMP_READ(_buf, 4); \
*(dest) = (_buf[3] << 24) | (_buf[2] << 16) | (_buf[1] << 8) | _buf[0]; \
}
#define MID_WRITE(buf, count) \
if (fwrite(buf, 1, count, mid_out) != (count)) \
{ \
free(mid_track_buf); \
snprintf(hmp2mid_error, sizeof(hmp2mid_error), mid_write_error_templ, \
strerror(errno)); \
return hmp2mid_error; \
}
#define MID_TRACK_BUF(buf, count) \
{ \
if ((mid_track_buf_used + count) > mid_track_buf_size) \
{ \
void *tmp = mid_track_buf; \
mid_track_buf = realloc(mid_track_buf, mid_track_buf_size + 65536); \
if (!mid_track_buf) \
{ \
free(tmp); \
return "Error could not allocate midi track memory"; \
} \
} \
memcpy(mid_track_buf + mid_track_buf_used, buf, count); \
mid_track_buf_used += count; \
}
static const char *hmp_read_error = "Error reading from hmp file";
static const char *mid_write_error_templ = "Error writing to mid file: %s";
static char hmp2mid_error[512];
/* The beginning of the midi header */
static const char midi_header1[10] = { 'M', 'T', 'h', 'd', 0, 0, 0, 6, 0, 1 };
/* The last 2 bytes of the midi header and track0 */
static const char midi_header2[21] = { 0, 0xC0, 'M', 'T', 'r', 'k', 0, 0, 0,
0x0B, 0, 0xFF, 0x51, 0x03, 0x18, 0x80, 0, 0, 0xFF, 0x2F, 0 };
const char *hmp2mid(hmp2mid_read_func_t read_func, void *hmp_in, FILE* mid_out)
{
unsigned char last_com = 0, buf[0x300];
unsigned int num_tracks, track_length = 0, i, t;
unsigned char *mid_track_buf = NULL;
int n1, n2, mid_track_buf_used, mid_track_buf_size = 0;
/* Read the header and verify that this is a hmp file */
HMP_READ(buf, 8);
buf[8] = 0;
if (strcmp((char *)buf, "HMIMIDIP"))
return "Error not a hmp file";
/* Discard the next 0x28 bytes, taking us to location 0x30 and read the
number of tracks there */
HMP_READ(buf, 0x30 - 8);
HMP_READ_DWORD(&num_tracks);
/* Discard bytes taking us to location 0x300 around which track 1 starts */
HMP_READ(buf, 0x300 - 0x34);
/* Now search for the end of track marker of track 0 */
HMP_READ(buf, 3);
while ((buf[0] != 0xFF) || (buf[1] != 0x2F) || (buf[2] != 0x00))
{
buf[0] = buf[1];
buf[1] = buf[2];
HMP_READ(buf + 2, 1);
}
/* Sofar so good, write out the midi header */
MID_WRITE(midi_header1, sizeof(midi_header1));
/* number of tracks is a 16 bit MSB word, better not have more then 65535
tracks :) */
buf[0] = (num_tracks >> 8) & 0xFF;
buf[1] = num_tracks & 0xFF;
MID_WRITE(buf, 2);
/* Write the last word of the header and track0 */
MID_WRITE(midi_header2, sizeof(midi_header2));
/* Read and convert all the tracks */
for (i = 1; i < num_tracks; i++)
{
/* Read and verify hmp track number */
HMP_READ_DWORD(&t);
if (t != i)
{
free(mid_track_buf);
return "Error invalid hmp track number";
}
/* Read number of bytes in this track */
HMP_READ_DWORD(&track_length);
/* Above we've already read the first 8 bytes of this track, adjust
track_lenght accordingly. */
track_length -= 8;
/* Read and skip the next 4 unidentified header bytes */
HMP_READ(buf, 4);
/* Sofar so good write midi track header */
MID_WRITE("MTrk", 4);
/* Now we need to write the track length, but we don't know that yet, so
the track gets written to a dynamicly growing buffer (which is hidden
in the MID_TRACK_BUF macro) */
mid_track_buf_used = 0;
/* And finally start the real conversion */
while (track_length > 0)
{
n1 = -1; /* -1 to "counter" the intital n1++ */
do
{
n1++;
HMP_READ(buf + n1, 1);
} while (!(buf[n1] & 0x80));
if (n1 >= 4)
{
free(mid_track_buf);
return "Error parsing hmp track";
}
for (n2 = 0; n2 <= n1; n2++)
{
unsigned char u = buf[n1-n2] & 0x7F;
if (n2 != n1)
u |= 0x80;
MID_TRACK_BUF(&u, 1);
}
HMP_READ(buf, 1);
if (buf[0] == 0xFF) /* meta? */
{
HMP_READ(buf + 1, 2);
HMP_READ(buf + 3, buf[2]);
MID_TRACK_BUF(buf, 3 + buf[2]);
if (buf[1] == 0x2F) /* end of track? */
{
if (buf[2] != 0x00)
{
free(mid_track_buf);
return "Error hmp meta end of track with non zero size";
}
break;
}
else
continue;
}
switch (buf[0] & 0xF0)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
t = 2;
break;
case 0xC0:
case 0xD0:
t = 1;
break;
default:
free(mid_track_buf);
return "Error invalid hmp command";
}
if (buf[0] != last_com)
MID_TRACK_BUF(buf, 1);
HMP_READ(buf + 1, t);
MID_TRACK_BUF(buf + 1, t);
last_com = buf[0];
}
if (track_length != 0)
{
free(mid_track_buf);
return "Error invalid track length";
}
/* write the midi track length */
buf [0] = mid_track_buf_used >> 24;
buf [1] = (mid_track_buf_used >> 16) & 0xFF;
buf [2] = (mid_track_buf_used >> 8) & 0xFF;
buf [3] = mid_track_buf_used & 0xFF;
MID_WRITE(buf, 4);
/* and the track itself */
MID_WRITE(mid_track_buf, mid_track_buf_used);
}
free (mid_track_buf);
return NULL;
}

31
main/hmp2mid.h Normal file
View file

@ -0,0 +1,31 @@
/* hmp 2 midi file conversion. The conversion algorithm is based on the
conversion algorithms found in d1x, d2x-xl and jjffe. The code is mine.
Copyright 2006 Hans de Goede
This file and the acompanying hmp2mid.c file are free software;
you can redistribute them and/or modify them under the terms of the GNU
Library General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
These files are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with these files; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef __HMP2MID_H
#define __HMP2MID_H
#include <stdio.h>
typedef size_t (*hmp2mid_read_func_t)(void *ptr, size_t size, size_t nmemb,
void *stream);
/* Returns NULL on success, otherwise a c-string with an error message */
const char *hmp2mid(hmp2mid_read_func_t read_func, void *hmp_in, FILE* mid_out);
#endif

View file

@ -449,10 +449,7 @@ int main(int argc,char **argv)
if (Inferno_verbose)
printf ("%s", TXT_VERBOSE_1);
arch_init();
cd_init();
if (init_graphics()) return 1;
//MD2211, 2006-08-30 : moving sound init *before* ReadConfigFile(), so that we restore music volume properly.
//------------ Init sound ---------------
if (!FindArg( "-nosound" )) {
@ -471,6 +468,14 @@ int main(int argc,char **argv)
else {
if (Inferno_verbose) printf( "\n%s",TXT_SOUND_DISABLED );
}
ReadConfigFile();
arch_init();
cd_init();
if (init_graphics()) return 1;
#ifdef NETWORK
if (!FindArg("-noserial"))
serial_active = 1;