Hi,

> I am trying to do the same thing (play DVD AC-3 through PC), and I
> haven't gotten anything to work, I can't figure out how to capture SPDIF
> input. Could you send me your mixer settings, and the spdifac3 program?
> I've got an emu10k1, but I might be able to find something from your
> mixer settings.

Here I send you the very simple spdifextract code; it extracts the data
stream from SPDIF stream (I changed the name because it has nothing to do
with AC3). It's so simple that it reads from its stdin and writes to its
stdout (but it can be easily modified to read/write files). To compile it
just do:

make spdifextract

and to use it:

arecord -D <in_dev> -f dat -t raw | spdifextract | ac3dec -D <5.1_dev>

Concerning the alsamixer, I don't think my VIA8235/ALC650 settings will
help you too much. One basic thing is that SPDIF is also referred to
as IEC958. I just had a look into the emu10k1 driver, and it looks that it
can have the following controls:

 - IEC958 TTL/Optical Capture Switch
 - IEC958 TTL/Optical Capture Volume

So maybe in the alsamixer, try to setup your IEC958 capture as active
(it looks like your Mic capture bar, you activate/deactivate with the
SPACE bar).

Try having a look to your /proc/asound/ files (using cat). They can
give you some idea of the status of your card (SPDIF input locked, etc.).
They will also tell you how many capture devices your card has (pcmXc).
Then, you can try as <in_dev> above in arecord:

hw:x,y  where x is the card (0,1,... ) and
              y is the device number (0,1,...)

Example: arecord -D hw:0,0 -f dat -t raw

When specifying -f dat, you fix to 48000 Hz, 16 bit little endian, stereo.

As output device for ac3dec, <5.1_dev> above, you can use (following
/usr/share/alsa/cards/EMU10K1):

ac3dec -D EMU10K1.pcm.surround51.0:x   where x is the card number.

I strongly recommend you to first try standard 44.1 KHz CD audio (by
playing for instance a CD in your DVD player) before the complex AC3. This
makes much easier the search of the SPDIF stream by just doing:

arecord -f cd | aplay

Good luck

Alejandro









#include <stdio.h>

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;

#define SPDIF_SYNC      0x4e1ff872

struct spdif_head_t {
        uint32_t        sync;
        uint8_t         type;
        uint8_t         bsmod;
        uint16_t        databits;       
};

int spdif_sync(FILE *in, struct spdif_head_t *header)
{
        int byte;
        uint32_t dword = 0xffffffff;

        while ((byte = fgetc(in)) != EOF) {
                dword = dword >> 8 | (byte << 24);
                if (dword == SPDIF_SYNC) {
                        header->sync = dword;
                        if ((byte = fgetc(in)) == EOF)
                                return -1;
                        header->type = byte;
                        if ((byte = fgetc(in)) == EOF)
                                return -1;
                        header->bsmod = byte;
                        if ((byte = fgetc(in)) == EOF)
                                return -1;
                        header->databits = byte;
                        if ((byte = fgetc(in)) == EOF)
                                return -1;
                        header->databits |= byte << 8;
                        return 0;
                }
        }
        
        return -1;
}

int main(int argc, char **argv)
{
        char *stream_name = "stdin";
        FILE *in = stdin, *out = stdout;
        fpos_t fpos;
        int i, byte0, byte1, pos, last_pos;
        struct spdif_head_t header;

        last_pos = 0;
        while (spdif_sync(in, &header) == 0) {
        /*      fgetpos(in, &fpos);
                pos = *((int *) &fpos);
                printf("Found SPDIF sync at %010lx: %5x, len %5x\n", pos, 
                                                        pos - last_pos,
                                                        header.databits / 8);
                last_pos = pos;
        */
                for (i = 0; i < header.databits / 8 / 2; i++) {
                        if ((byte1 = fgetc(in)) == EOF)
                                break;
                        if ((byte0 = fgetc(in)) == EOF)
                                break;
                        fputc(byte0, out);
                        fputc(byte1, out);
                }
        }

        return 0;
}

Reply via email to