view testpl.c @ 0:32250b436bca

Initial re-import.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 28 Sep 2012 01:54:23 +0300
parents
children fc097f7717df
line wrap: on
line source

#include "jss.h"
#include "jssmod.h"
#include "jssmix.h"
#include "jssplr.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <SDL.h>


static const char patNoteTable[12][3] =
{
    "C-", "C#", "D-",
    "D#", "E-", "F-",
    "F#", "G-", "G#",
    "A-", "A#", "B-"
};


#define jmpNMODEffectTable (36)
static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";


void printRow(FILE * f, JSSPattern * p, int row)
{
    int j, k;
    char c;
    JSSNote *n;

    if (!p)
        return;

    n = &(p->data[p->nchannels * row]);

    fprintf(f, "%.2x: ", row);
    
    k = p->nchannels < 5 ? p->nchannels : 5;

    for (j = 0; j < k; j++)
    {
        switch (n->note)
        {
            case jsetNotSet:
                fprintf(f, "... ");
                break;
            case jsetNoteOff:
                fprintf(f, "=== ");
                break;
            default:
                fprintf(f, "%s%i ", patNoteTable[n->note % 12], n->note / 12);
                break;
        }

        if (n->instrument != jsetNotSet)
            fprintf(f, "%.2x ", n->instrument + 1);
        else
            fprintf(f, ".. ");

        if (n->volume == jsetNotSet)
            fprintf(f, ".. ");
        else if (n->volume >= 0x00 && n->volume <= 0x40)
            fprintf(f, "%.2x ", n->volume);
        else
        {
            switch (n->volume & 0xf0)
            {
                case 0x50: c = '-'; break;
                case 0x60: c = '+'; break;
                case 0x70: c = '/'; break;
                case 0x80: c = '\\'; break;
                case 0x90: c = 'S'; break;
                case 0xa0: c = 'V'; break;
                case 0xb0: c = 'P'; break;
                case 0xc0: c = '<'; break;
                case 0xd0: c = '>'; break;
                case 0xe0: c = 'M'; break;
                default:   c = '?'; break;
            }
            fprintf(f, "%c%x ", c, (n->volume & 0x0f));
        }

        if (n->effect >= 0 && n->effect < jmpNMODEffectTable)
            fprintf(f, "%c", jmpMODEffectTable[n->effect]);
        else if (n->effect == jsetNotSet)
            fprintf(f, ".");
        else
            fprintf(f, "?");

        if (n->param != jsetNotSet)
            fprintf(f, "%.2x|", n->param);
        else
            fprintf(f, "..|");

        n++;
    }
}


void audioCallback(void *userdata, Uint8 *stream, int len)
{
    JSSMixer *d = (JSSMixer *) userdata;

    if (d != NULL)
    {
        jvmRenderAudio(d, stream, len / jvmGetSampleSize(d));
    }
}


int main(int argc, char *argv[])
{
    SDL_AudioSpec *a_desired, *a_obtained;
    DMResource *inFile;
    char *sname = NULL;
    int result = -1;
    JSSModule *m;
    JSSMixer *d;
    JSSPlayer *p;
    int buflen = 4096;

    if (argc > 1)
        sname = argv[1];

    // Open the files
    if (sname == NULL)
        inFile = dmf_create_stdio_stream(stdin);
    else if ((inFile = dmf_create_stdio(sname)) == NULL)
    {
        fprintf(stderr, "Error opening input file '%s'. (%s)\n", sname, strerror(errno));
        return 1;
    }
        
    // Initialize miniJSS
    fprintf(stderr, "Initializing miniJSS\n");
    jssInit();

    
    // Read module file
    fprintf(stderr, "Reading file: %s\n", sname);
#ifdef JSS_SUP_XM
    fprintf(stderr, "* Trying XM...\n");
    result = jssLoadXM(inFile, &m);
#endif
#ifdef JSS_SUP_JSSMOD
    if (result != 0)
    {
        size_t bufsize = dmfsize(inFile);
        Uint8 *buf = dmMalloc(bufsize);
        fprintf(stderr, "* Trying JSSMOD...\n");
        if (dmfread(buf, 1, bufsize, inFile) != bufsize)
        {
            fprintf(stderr, "Error reading file!\n");
            return 2;
        }
        result = jssLoadJSSMOD(buf, bufsize, &m);
        dmFree(buf);
    }
#endif
    dmf_close(inFile);

    if (result != 0)
    {
        fprintf(stderr, "Error loading module file: %d\n", result);
        return 3;
    }


    // Initialize SDL audio
    fprintf(stderr, "Pre-initializing params\n");
    a_desired = dmMalloc(sizeof(SDL_AudioSpec));
    a_obtained = dmMalloc(sizeof(SDL_AudioSpec));
    if (!a_desired || !a_obtained)
    {
        fprintf(stderr, "Could not allocate SDL shit\n");
        return 3;
    }

    a_desired->freq     = 48000;
    a_desired->format   = AUDIO_S16SYS;
    a_desired->channels = 2;
    
    // Initialize mixing device
    fprintf(stderr, "Initializing miniJSS mixer with: %d, %d, %d\n",
        JSS_AUDIO_S16, a_desired->channels, a_desired->freq);

    d = jvmInit(JSS_AUDIO_S16, a_desired->channels, a_desired->freq, JMIX_AUTO);
    if (!d) {
        fprintf(stderr, "jvmInit() returned NULL\n");
        return 3;
    }
    
    a_desired->samples  = buflen;
    a_desired->callback = audioCallback;
    a_desired->userdata = (void *) d;

    // Open the audio device
    fprintf(stderr, "Trying to init SDL with: %d, %d, %d\n",
        a_desired->format, a_desired->channels, a_desired->freq);
    
    if (SDL_OpenAudio(a_desired, a_obtained) < 0)
    {
        fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
        return 4;
    }
    
    fprintf(stderr, "Got: %d, %d, %d\n",
        a_obtained->format, a_obtained->channels, a_obtained->freq);
    
    if ((a_obtained->format   != a_desired->format) ||
        (a_obtained->channels != a_desired->channels) ||
        (a_obtained->freq     != a_desired->freq))
    {
        fprintf(stderr, "Could not get wanted audio parameters from SDL!\n");
        return 8;
    }

    free(a_desired);

    // Initialize player
    p = jmpInit(d);
    if (!p)
    {
        fprintf(stderr, "jmpInit() returned NULL\n");
        return 4;
    }
    
    // Set callback
    jvmSetCallback(d, jmpExec, p);
    
    // Initialize playing
    jmpSetModule(p, m);
    jmpPlayOrder(p, 0);
    jvmSetGlobalVol(d, 60);

    // okay, main loop here ... "play" module and print out info
    printf("----------------------------------------------------\n");
    SDL_PauseAudio(0);
    while (p->isPlaying)
    {
        int r = p->iRow;
        while (r == p->iRow && p->isPlaying)
            SDL_Delay(50);

        printRow(stdout, p->pPattern, p->iRow);
        printf("\n");
    }
    
    printf("----------------------------------------------------\n");

    // Free module data
    jmpClose(p);
    jvmClose(d);
    jssFreeModule(m);
    m = NULL;

    return 0;
}