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; }