32X Audio

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

32X Audio

Post by ob1 » Thu Jun 05, 2008 8:48 am

Here everything relative to 32X audio.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Jun 05, 2008 5:27 pm

Genesis Side

PWM Control Reg: 0x00A15130
b15 - b12: -
b11 - b8: TM3 - TM0 = SH interrupt time = 1 - 15 = int once each N x Cycle Reg clks, 0 = 16 x
b7: RTP = 1 = enable DREQ 1 to SH, 0 = disable
b6 - b4: -
b3 - b2: RMD0 - RMD1 = Right mode = 00 = off, 01 = Right channel, 10 = Left channel, 11 = -
b1 - b0: LMD0 - LMD1 = Left mode = 00 = off, 01 = Right channel, 10 = Left channel, 11 = -
You cannot set both to the same channel. This is used to turn off channels, or switch the stereo.
Also, the cycle counter doesn't advance if both are off. If only one is off, no sound is produced,
but the data in the FIFO is discarded at each sample period.

PWM Cycle Reg: 0x00A15132
b15 - b12: -
b11 - b0: Cycle count. Sample period is SH clk / (cycle count - 1), with 0 = full count (4095).

PWM Left Channel Pulse Width Reg: 0x00A15134
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).

PWM Right Channel Pulse Width Reg: 0x00A15136
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).

PWM Mono Channel Pulse Width Reg: 0x00A15138
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).
This value is written through to both the right and left pulse width registers.


32X Side

Interrupt Control Reg: 0x20004000
b15 - b1: not discussed as not part of audio :)
b0: PWM = 0 = PWM timer interrupt masked, 1 = enabled
Refer to info on TM3-0 for interrupt period.

PWM Interrupt Clear Reg: 0x2000401C
b15 - b0: x = any write clears the PWM interrupt flag

PWM Control Reg: 0x20004030
b15 - b12: -
b11 - b8: TM3 - TM0 = SH interrupt time = 1 - 15 = int once each N x Cycle Reg clks, 0 = 16 x
b7: RTP = 1 = enable DREQ 1 to SH, 0 = disable
b6 - b4: -
b3 - b2: RMD0 - RMD1 = Right mode = 00 = off, 01 = Right channel, 10 = Left channel, 11 = -
b1 - b0: LMD0 - LMD1 = Left mode = 00 = off, 01 = Right channel, 10 = Left channel, 11 = -
You cannot set both to the same channel. This is used to turn off channels, or switch the stereo.

PWM Cycle Reg: 0x20004032
b15 - b12: -
b11 - b0: Cycle count. Sample period is SH clk / (cycle count - 1), with 0 = full count (4095).

PWM Left Channel Pulse Width Reg: 0x20004034
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).

PWM Right Channel Pulse Width Reg: 0x20004036
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).

PWM Mono Channel Pulse Width Reg: 0x20004038
b15: FULL = 1 = FIFO for this channel is full, 0 = not full (but might not be empty)
b14: EMPTY = 1 = FIFO for this channel is empty, 0 = not empty (but might not be full)
b13 - b12: -
b11 - b0: Pulse width. Wave amp is width - 1, with 0 = full amp (4095).
This value is written through to both the right and left pulse width registers.


Writing the FIFO when it is full registers the value while discarding the oldest entry. The FIFO is
three deep.

TotOOntHeMooN
Interested
Posts: 38
Joined: Sun Jun 01, 2008 1:12 pm
Location: Lyon, France
Contact:

Post by TotOOntHeMooN » Fri Jul 04, 2008 12:40 pm

What's new about the 32X sound ?
Nobody is working on it ?

If anybody was interested, I own a large XI's samples library.
Is it possible to use it with the 32X channels ?

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sun Jan 20, 2013 9:57 pm

What would an example of a piece of code be to play some sound?

In my main loop I am trying to make a sound (any sound) by setting these registers based on my understanding

Code: Select all

MARS_PWM_CTRL = 5; //0x20004030
MARS_PWM_CYCLE = pwmCycle; //0x20004032
MARS_PWM_LEFT = pwmLeft; // 0x20004034
MARS_PWM_RIGHT = pwmRight; // 0x20004036
where pwmCycle, pwmLeft, pwmRight are ints set by user input to be 0-4095 values so that I can experiment.

In Gens I get a series of clicks and some brief buzzing either while I am changing the cycle or more rarely the left or right values. But it's not a consistent tone or anything. Maybe I need to put more values in the FIFO queue to make a consistent sound?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sun Jan 20, 2013 10:20 pm

I do something like this to init the PWM

Code: Select all

    // init the sound hardware
    MARS_PWM_MONO = 1;
    MARS_PWM_MONO = 1;
    MARS_PWM_MONO = 1;
    if (MARS_VDP_DISPMODE & MARS_NTSC_FORMAT)
        MARS_PWM_CYCLE = (((23011361 << 1)/SAMPLE_RATE + 1) >> 1) + 1; // for NTSC clock
    else
        MARS_PWM_CYCLE = (((22801467 << 1)/SAMPLE_RATE + 1) >> 1) + 1; // for PAL clock
    MARS_PWM_CTRL = 0x0185; // TM = 1, RTP, RMD = right, LMD = left

    sample = SAMPLE_MIN;
    /* ramp up to SAMPLE_CENTER to avoid click in audio (real 32X) */
    while (sample < SAMPLE_CENTER)
    {
        for (ix=0; ix<(SAMPLE_RATE*2)/(SAMPLE_CENTER - SAMPLE_MIN); ix++)
        {
            while (MARS_PWM_MONO & 0x8000) ; // wait while full
            MARS_PWM_MONO = sample;
        }
        sample++;
    }
The loop merely ramps the audio from the minimum sample value to the center value. Those defines are normally

Code: Select all

#define SAMPLE_RATE    22050
#define SAMPLE_MIN         2
#define SAMPLE_CENTER    517
#define SAMPLE_MAX      1032
The min/max/center will vary depending on the sample rate.

EDIT: You make PWM samples by starting with signed samples. Scale them to +/-(SAMPLE_CENTER - SAMPLE_MIN). Then add SAMPLE_CENTER to the value. Note that SAMPLE_CENTER - SAMPLE_MIN for the above is 515, which is close to 512. Say your sample is signed bytes - that's -128/+127, so you could shift the sample (arithmetically) left 2 bits for -512/+508, which is good enough. So to convert signed bytes to PWM, you could just do (sample[ix] << 2) + SAMPLE_CENTER and get a nice sound. It gets more complicated when you start adding sounds and scaling for volume.
/EDIT

Note how I set the control register to $185 - that sets the interrupt rate for one sample (I don't use PWM ints, but that also affects the DREQ for DMA), sets the DREQ enable, and enables left to left and right to right (see my big post at the top for details of the bits).

You have three ways to play samples at this point: you can poll the FIFO (see the big post for FIFO bits), storing the new sample each time the FIFO is not full; you can enable PWM ints (see the big post for int bits) and store the new sample each time an int occurs (actually, you want to set the int for more than one sample and then store multiple samples in the int code for best speed); and finally, you can set the DMA to play the sample. I used polling for Wolf32X, mainly because I hadn't gotten my DMA code working by that point, but these days I use DMA. In fact, in my XM player example, I use interrupt driven DMA so that I don't have to poll the DMA done flag.

I suggest you look at my XM player code: viewtopic.php?t=1253

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sat Jan 26, 2013 4:36 pm

...but these days I use DMA. In fact, in my XM player example, I use interrupt driven DMA so that I don't have to poll the DMA done flag.

I suggest you look at my XM player code: viewtopic.php?t=1253
I have taken a look at the xmplayer1.1 src, where in the src are you actually using DMA to send the samples?

I've gotten your player to play my own .xm track, it's pretty cool.

As a general statement, if I want to have sound effects like jump, punch & kick sounds, do I want to try to create them as .xm files and plug them in the same way you would do songs? Or should I do something totally different?

Code: Select all

    sample = SAMPLE_MIN;
    /* ramp up to SAMPLE_CENTER to avoid click in audio (real 32X) */
    while (sample < SAMPLE_CENTER)
    {
        for (ix=0; ix<(SAMPLE_RATE*2)/(SAMPLE_CENTER - SAMPLE_MIN); ix++)
        {
            while (MARS_PWM_MONO & 0x8000) ; // wait while full
            MARS_PWM_MONO = sample;
        }
        sample++;
    } 
I still have questions about this code. For example, is this still part of the init code or just an example of playing a single sample?

What is the purpose of the inner loop exactly? Does setting MARS_PWM_MONO play that sample's value automatically? Every time I play a sound do I have to similarly loop to "ramp up" and keep filling the PWM register until I reach the target sample's amplitude?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Jan 26, 2013 11:56 pm

The DMA code is all in hw_32x.c. The slave() function inits the DMA, and calls slave_dma1_handler() once to start the DMA. At that point, any time the DMA finishes, a DMA Transfer End interrupt occurs, which is set to slave_dma1_handler(). That causes the next DMA to be started, and fills the next buffer.

The sound.c file has the fill_buffer() function. This functions locks the mixer (since we have two CPUs that could be trying to access the same structures), calls do_music() to process the music score and mix the music channels, then calls do_sfx() to mix any sound effects.

The do_sfx() function in the file doesn't actually mix any sound effects since this was a music player. But this is where you would do so. If you look at the do_music() function, the main function to mix channels is MixSamples(). That function is in assembly for best speed, and is in the crt0.s file. Just look for _MixSamples in crt0.s.

Code: Select all

! void MixSamples(void *mixer, int16_t *buffer, int32_t cnt, int32_t scale);
! On entry: r4 = mixer pointer
!           r5 = buffer pointer
!           r6 = count (number of stereo 16-bit samples)
!           r7 = scale (global volume - possibly fading, 0 - 64)
        .align  4
        .global _MixSamples
_MixSamples:
This function is called from C code like in the do_music() function

Code: Select all

                    MixSamples(mix, buffer, num_samples, cscale);
The first arg is a pointer to the mixer structure. The second is a pointer to ram where the samples will be mixed. The third is the number of samples to mix. The fourth is the scale for the sound (0=off, to 64=max).

The mixer structure is in xmp.h (part of libxmp) and is

Code: Select all

typedef struct
{
    const int8_t *data;         // points to sample data rom, or 0 for channel off
    uint32_t position;          // current position in the data (fixed point 18.14)
    uint32_t increment;         // step size (fixed point 18.14) for pitch
    uint32_t length;            // size of data (fixed point 18.14)
    uint32_t loop_length;       // size of section to loop (fixed point 18.14) or 0 for no loop
    int8_t   volume;            // 0 to 64
    uint8_t  pan;               // 0 = left, 255 = right
    uint8_t  pad[2];            // pad to 24 bytes
} mixer_t;
You would set up any number of these mixer structures (maybe an array of 4 or 8 for 4 or 8 sound effects). You would then set the fields for the sample to play. A non-looping sound effect would require setting data to a pointer to signed 8-bit mono samples, position to 0, increment to (SAMPLE_RATE << 14)/(sample rate of sample), the length to the length in samples << 14, loop length to 0, the volume to the relative volume of the sample, and the pan according to where it is in stereo.

In do_sfx(), you would loop through your array of mixers, and if they both have data set and volume != 0, call MixSample() on that mixer.
Last edited by Chilly Willy on Sun Jan 27, 2013 12:02 am, edited 1 time in total.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Jan 26, 2013 11:59 pm

I still have questions about this code. For example, is this still part of the init code or just an example of playing a single sample?

What is the purpose of the inner loop exactly? Does setting MARS_PWM_MONO play that sample's value automatically? Every time I play a sound do I have to similarly loop to "ramp up" and keep filling the PWM register until I reach the target sample's amplitude?
It's part of the init code to try to avoid a big CLICK when you start the game. The 32X starts with the PWM output at 0, the writes of 1 to the MONO channel fills the PWM FIFO with 1, then the loop gradually changes the PWM output from 1 to the center sample value, which is the relative 0 point for silence on the PWM output.

After that loop, the DMA takes over setting the sample outputs.

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Mon Jan 28, 2013 4:32 pm

Thanks I am starting to piece it together now. The games template is based on your earlier tictactoe demo so I am trying to port my changes since then to the new crt0.s and mars.ld.

I have some sound FX in xm format from openmpt so once I get the port working I'll be able add sound quickly thanks to the library and these tools.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Mon Jan 28, 2013 6:05 pm

xm, or xi? I wrote some code to load an xi file a while back...

Code: Select all

instrument_t *load_xi(char *fname, int smp)
{
    instrument_t *in;
    FILE *xif;
    char temp[256];
    int i, j, n, t;

    xif = fopen(fname, "rb");
    fread(temp, 1, 21, xif);
    if (memcmp(temp, "Extended Instrument: ", 21))
    {
        printf("Not an XI file\n");
        fclose(xif);
        return (instrument_t *)NULL;
    }

    // read name
    i = -1;
    do
    {
        i++;
        temp[i] = fgetc(xif);
    } while (temp[i] != 0x1A);
    temp[i] = 0;
    printf("Instrument name: %s\n", temp);

    // skip tracker name
    fseek(xif, 20, SEEK_CUR);

    // read version
    j = fgetc(xif) | (fgetc(xif) << 8);
    if (j != 0x0102)
    {
        printf("Wrong version: 0x%04X\n", j);
        fclose(xif);
        return (instrument_t *)NULL;
    }

    in = malloc(sizeof(instrument_t));
    if (!in)
    {
        printf("Ran out of memory\n");
        fclose(xif);
        return (instrument_t *)NULL;
    }

    // skip note instrument table
    fseek(xif, 96, SEEK_CUR);

    // read envelopes
    for (i=0; i<12; i++)
    {
        j = fgetc(xif) | (fgetc(xif) << 8);
        in->volume.x[i] = j;
        j = fgetc(xif) | (fgetc(xif) << 8);
        in->volume.y[i] = j;
    }
    for (i=0; i<12; i++)
    {
        j = fgetc(xif) | (fgetc(xif) << 8);
        in->pan.x[i] = j;
        j = fgetc(xif) | (fgetc(xif) << 8);
        in->pan.y[i] = j;
    }

    // various values
    in->volume.points = fgetc(xif);
    in->pan.points = fgetc(xif);
    in->volume.sustain = fgetc(xif);
    in->volume.loop_start = fgetc(xif);
    in->volume.loop_end = fgetc(xif);
    in->pan.sustain = fgetc(xif);
    in->pan.loop_start = fgetc(xif);
    in->pan.loop_end = fgetc(xif);
    in->volume.type = fgetc(xif);
    in->pan.type = fgetc(xif);
    in->vibrato.type = fgetc(xif);
    in->vibrato.sweep = fgetc(xif);
    in->vibrato.depth = fgetc(xif);
    in->vibrato.rate = fgetc(xif);
    j = fgetc(xif) | (fgetc(xif) << 8);
    in->volfade = j;

    // skip res and extra
    fseek(xif, 22, SEEK_CUR);

    // get number of samples in this instrument
    n = fgetc(xif) | (fgetc(xif) << 8);
    printf("%d samples in this instrument\n", n);
    if (smp >= n)
        smp = 0; // smp too big - use first sample

    // skip to desired sample header
    if (smp)
        fseek(xif, 40*smp, SEEK_CUR);

    // read sample header
    j = fgetc(xif) | (fgetc(xif) << 8) | (fgetc(xif) << 16) | (fgetc(xif) << 24);
    in->length = j;
    printf("Sample length: %d\n", j);
    j = fgetc(xif) | (fgetc(xif) << 8) | (fgetc(xif) << 16) | (fgetc(xif) << 24);
    in->loop_start = j;
    printf("Loop start: %d\n", j);
    j = fgetc(xif) | (fgetc(xif) << 8) | (fgetc(xif) << 16) | (fgetc(xif) << 24);
    in->loop_end = j;
    printf("Loop end: %d\n", j);
    in->volume.base = fgetc(xif);
    printf("Volume: %d\n", in->volume.base);
    in->finetune = fgetc(xif);
    printf("Finetune: %d\n", in->finetune);
    t = fgetc(xif);
    printf("Type: 0x%02X\n", in->type);
    in->pan.base = fgetc(xif);
    printf("Pan: %d\n", in->volume.base);
    in->relative = fgetc(xif);
    printf("Relative: %d\n", in->relative);

    // skip res
    fgetc(xif);

    // read sample name
    fread(temp, 1, 22, xif);
    temp[22] = 0;
    printf("Sample name: %s\n", temp);

    // skip other sample headers
    if (n > 1)
        fseek(xif, (n-1-smp)*40, SEEK_CUR);

    // skip to desired sample data
    if (smp)
        fseek(xif, in->length*smp, SEEK_CUR);

    // read first sample deltas
    if (t & 0x10)
    {
        // 16-bit sample
        printf("Processing 16-bit sample..\n");
        in->length /= 2;
        in->loop_start /= 2;
        in->loop_length /= 2;
        in->data = malloc((t & 0x02) ? in->loop_start + in->loop_length*2 : in->length);
        if (!in->data)
        {
            printf("Ran out of memory\n");
            free(in);
            fclose(xif);
            return (instrument_t *)NULL;
        }
        n = 0;
        for (i=0; i<in->length; i++)
        {
            j = fgetc(xif) | (fgetc(xif) << 8);
            n += (int16_t)j; // delta to sample
            in->data[i] = n >> 8;
        }
    }
    else
    {
        // 8-bit sample
        printf("Processing 8-bit sample..\n");
        in->data = malloc((t & 0x02) ? in->loop_start + in->loop_length*2 : in->length);
        if (!in->data)
        {
            printf("Ran out of memory\n");
            free(in);
            fclose(xif);
            return (instrument_t *)NULL;
        }
        n = 0;
        for (i=0; i<in->length; i++)
        {
            j = fgetc(xif);
            n += (int8_t)j; // delta to sample
            in->data[i] = n;
        }
    }

    if (t & 0x02)
    {
        // handle bidi looping
        printf("Unrolling BIDI loop...\n");
        for (i=0; i<in->loop_length; i++)
            in->data[in->loop_start + in->loop_length + i] = in->data[in->loop_start + in->loop_length - i - 1];
        in->loop_length *= 2;
        in->length = in->loop_start + in->loop_length;
    }

    if (!(t & 0x03))
    {
        // not a looping instrument - clear loop variables
        in->loop_start = 0;
        in->loop_length = 0;
    }

    return in;
}

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sat Feb 09, 2013 2:41 pm

I have an .xm file from OpenMPT

download my kung-fu-kick.xm sample here

It's currently set to 2 channels, I don't know anything about sound effects or music, so I am not sure if there are any other settings that I miss.

I've tried loading it and playing it in XMPlayer, to see if it would work, but it doesn't seem to have a valid sound when played in KFusion. It sounds like a brief pop.

Here is the output of xmconvert
xmplayer-v1.1\xmplayer\music>..\to
ols\xmconvert -v -s -e ..\kung-fu\kung-fu-kick.xm
read xm
xm id : Extended Module:
xm name: →OpenMPT 1.21.01.00 ♦☺§
xm trkr: OpenMPT 1.21.01.00 ♦☺§
xm vers: 0104
xm head: 21
xm song: 1
xm rest: 0
xm chnl: 2
xm patt: 1
xm inst: 2
xm flag: 1 (Linear)
xm tmpo: 1
xm BPM : 125

Order: 00

empty pattern... creating empty pattern
Packed 64 unpacked 128
ins samp: 0
ins hdln: 0
ins name:
ins samp: 0
ins hdln: 0
ins name:
What's this "empty pattern"?

My workflow for this sound was wav > OpenMPT > save as .xm > xmconvert > xmplayer.

I know this works for other sounds as I've gone midi > xm > xmplayer and the sound plays fine in KFusion.

What tools create .xi?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Feb 09, 2013 7:47 pm

Why are you trying to use xm (or even xi) to play a sound effect? :shock:

Just make a mixer struct, fill in the values, the call MixSample() on it. The proto for MixSample() is

Code: Select all

void MixSamples(void *mixer, int16_t *buffer, int32_t cnt, int32_t scale);
where mixer is a pointer to the mixer struct (in xmp.h), buffer is the sound buffer you are mixing the sound with, cnt is the number of samples you need mixed, and scale is the volume where 64 = 1.0 (you give a volume of 0 to 64, which represents 0.0 to 1.0).

I went over all that before... I suppose I can add some code to my xmplayer example that plays a sound in addition to the music when you push a button. I'll post that later today.

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sat Feb 09, 2013 7:59 pm

I thought I was asking earlier in the thread if this was the right way to do it. If there were a better way to do it, I would gladly use that format! I've never worked with sound in digital formats before or worked on code that produced sound.
Why are you trying to use xm (or even xi) to play a sound effect? Shocked
I have a sound file on my PC, lets say in wav format. I want to hear something approximately like that sound in my 32X game. What is the best way to do that?
Just make a mixer struct, fill in the values
How do I determine the values for

Code: Select all

const int8_t *data;         // points to sample data rom, or 0 for channel off?
What tools or techniques can be used to automate it producing the data, from a source sound?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Feb 09, 2013 9:07 pm

You want to save any WAV sounds as 8-bit signed samples in raw format. You can use any sound editor to do so. I use Audacity:

http://audacity.sourceforge.net/

You can resample the audio for whatever rate you want - a lower rate uses less space, but doesn't sound as good. A higher rate sounds better, but uses more space. Most old games used 1/4th CD rate, or 11025 Hz.

Once you have the sound saved as 8-bit signed raw pcm data, you can include it in an assembly file like this

Code: Select all

    .global sound1
sound1:
    .incbin "sound1.raw"
In the c file, you would have

Code: Select all

extern char sound1[];
which defines the sound as an external (in another file) array of chars. You can then use it for the data field using just "sound1" as the pointer. If you wished to skip into the sound a ways, you would use "&sound1[offset]" as the pointer.

ammianus
Very interested
Posts: 124
Joined: Sun Jan 29, 2012 2:10 pm
Location: North America
Contact:

Post by ammianus » Sat Feb 09, 2013 11:39 pm

Ah that is certainly simpler. I already am working with audicity so now I know how to do it.

Thanks for the help

Post Reply