summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2011-10-29 18:59:57 +0100
committernorly <ny-git@enpas.org>2011-10-29 18:59:57 +0100
commitd2bb4247717d2cc89a8428cae6ae77067d86129d (patch)
treed6b0f1abf9b10afee6b2be02e6d654cfa25e3040
Initial commit.
Basically the old code from 2006/07, slightly modified to compile on modern GCC/Linux. Changed the tool names.
-rw-r--r--.gitignore2
-rw-r--r--Makefile11
-rw-r--r--README.md57
-rwxr-xr-xac32spdif.c182
-rwxr-xr-xdts2spdif.c177
5 files changed, 429 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c6e429
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+ac32spdif
+dts2spdif
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bf64657
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+all: ac32spdif dts2spdif
+
+ac32spdif: ac32spdif.c
+ cc -O2 -o ac32spdif ac32spdif.c
+
+dts2spdif: dts2spdif.c
+ cc -O2 -o dts2spdif dts2spdif.c
+
+.PHONY: clean
+clean:
+ rm -f ac32spdif dts2spdif
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ed9a663
--- /dev/null
+++ b/README.md
@@ -0,0 +1,57 @@
+S/PDIF tools
+===========
+
+These simple programs convert raw AC3 (Dolby Digital, A/52) and DTS streams
+into WAV files containing the S/PDIF fake PCM encoding thereof. This means
+that if such a .wav file is replayed correctly bit-by-bit via the S/PDIF
+output of a device and supplied to a standards compliant decoder, it
+will be recognized as a standards compliant AC3/DTS stream,
+indistinguishable from a stream generated e.g. by a DVD player.
+
+This is useful to e.g. author CDs containing compressed multichannel
+data (such as DTS encoded CDs that commercially available).
+Take care: Playing back the files produced via speakers at high volume
+may damage these or your hearing.
+
+
+A note about coding style
+-------------------------
+
+These sources are very old (from around 2006/2007) and show my coding
+abilities back then when I started with C. I hope to clean this up
+and modernize it at some point in the future.
+
+
+ac32spdif
+---------
+
+This tool takes a raw .ac3 file and converts it into a .wav file of the
+same sample rate containing one AC3 frame plus padding zeros for the
+remaining time of that frame's time slot.
+
+
+dts2spdif
+---------
+
+In a similar fashion, this tool translates a .dts file to a .wav file.
+Currently it only supports 16 bit encapsulation, i.e. the data stream
+is included in the .wav file 1:1.
+The DTS specification also defines a 14 bit format for use with CDs
+where there is a possibility that the data will be played back via
+speakers in order to reduce the possibility of speaker/hearing damage
+when the medium is played back without a DTS decoder. In this case,
+only the lower 14 bits of a word would be used, with the high 2 bits
+set to zero. This encoding may be added to dts2spdif later on.
+
+
+License
+-------
+
+As usual, this code comes with no warranty whatsoever. I am especially
+not responsible if you blow up your speakers or ears using these tools.
+
+Do whatever you like with this code, but if you use it for your own
+application I would appreciate an attribution note in the documentation.
+Thanks!
+
+ -- norly
diff --git a/ac32spdif.c b/ac32spdif.c
new file mode 100755
index 0000000..a1ab79f
--- /dev/null
+++ b/ac32spdif.c
@@ -0,0 +1,182 @@
+
+#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+#include <memory.h>
+
+//#include "fs_codes.h"
+
+
+short bitrates[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160,
+192, 224, 256, 320, 384, 448, 512, 576, 640 };
+
+short fsize44[] = { 70, 88, 105, 122, 140, 175, 209, 244, 279, 349,
+418, 488, 558, 697, 836, 976, 1115, 1254, 1394 };
+
+unsigned long DecFS(char sratecode, unsigned long fsizecode)
+{
+ switch (sratecode)
+ {
+ case 0:
+ return (bitrates[fsizecode / 2] * 2);
+ case 1:
+ return ((fsizecode % 2) ? fsize44[fsizecode / 2] : fsize44[fsizecode / 2] - 1);
+ case 2:
+ return (bitrates[fsizecode / 2] * 3);
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+
+
+
+struct WAVEHEADER {
+ unsigned long ChunkID;
+ unsigned long ChunkSize;
+ unsigned long Format;
+ unsigned long SubChunk1ID;
+ unsigned long SubChunk1Size;
+ unsigned short AudioFormat;
+ unsigned short NumChannels;
+ unsigned long SampleRate;
+ unsigned long ByteRate;
+ unsigned short BlockAlign;
+ unsigned short BitsPerSample;
+ unsigned long SubChunk2ID;
+ unsigned long SubChunk2Size;
+};
+
+
+struct AC3PREAMBLE {
+ unsigned short sync1;
+ unsigned short sync2;
+ unsigned char burst_infoLSB;
+ unsigned char burst_infoMSB;
+ unsigned short lengthcode;
+};
+
+char burst[6144];
+
+FILE *infile, *outfile;
+
+unsigned long bytesread;
+unsigned long payloadbytes;
+char sampleratecode;
+unsigned long framesizecode;
+
+struct AC3PREAMBLE ac3p = { 0xF872, 0x4E1F, 1, 0, 0x3800 };
+struct WAVEHEADER wavhdr = { 0x46464952,
+ 0,
+ 0x45564157,
+ 0x20746D66,
+ 16,
+ 1,
+ 2,
+ 0,
+ 0,
+ 4,
+ 16,
+ 0x61746164,
+ 0 };
+
+unsigned long i;
+char temp;
+
+int main( int argc, char *argv[ ], char *envp[ ] )
+{
+ if (argc < 3)
+ {
+ printf("Wrong syntax. AC3PACK <In.ac3> <Out.wav>.\n");
+ return 0;
+ }
+
+ infile = fopen(argv[1], "rb");
+ outfile = fopen(argv[2], "wb");
+ //fseek(outfile, SEEK_SET, 44);
+ fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);
+
+
+
+ for(;;)
+ {
+ memset (burst, 0, 6144);
+ bytesread = fread(&burst[8], 1, 6, infile);
+ if (bytesread < 6)
+ {
+ printf ("EOF reached (Frame Header reading)!\nCurrent position in INFILE: %i\n", ftell(infile));
+ break;
+ }
+ if ((burst[8] != 0x0B) || (burst[9] != 0x77))
+ {
+ printf("ERROR: INVALID SYNCWORD !\nCurrent position in INFILE: %i\n", ftell(infile));
+ break;
+ }
+ framesizecode = (burst[12] & 63);
+ sampleratecode = ((burst[12] & 192) / 64);
+
+ if (wavhdr.SampleRate == 0)
+ {
+ printf ("First Sampleratecode: %i\n", sampleratecode);
+
+ switch (sampleratecode)
+ {
+ case 0:
+ wavhdr.SampleRate = 48000;
+ wavhdr.ByteRate = 192000;
+ break;
+ case 1:
+ wavhdr.SampleRate = 44100;
+ wavhdr.ByteRate = 176000;
+ break;
+ case 2:
+ wavhdr.SampleRate = 32000;
+ wavhdr.ByteRate = 128000;
+ break;
+ default:
+ wavhdr.SampleRate = 48000;
+ wavhdr.ByteRate = 192000;
+ }
+ }
+
+ payloadbytes = DecFS (sampleratecode, framesizecode);
+ payloadbytes *= 2;
+
+ bytesread = fread (&burst[14], 1, payloadbytes - 6, infile);
+ if ((bytesread + 6) < payloadbytes)
+ {
+ printf ("EOF reached (Burst Reading)!\nCurrent position in INFILE: %i\n", ftell(infile));
+ printf ("Frame size: %i .. Bytes read: %i\n", payloadbytes, bytesread);
+ break;
+ }
+ ac3p.burst_infoMSB = (burst[13] & 7);
+ ac3p.lengthcode = (short)(payloadbytes * 8);
+
+ for (i = 8; i < (payloadbytes + 8); i += 2)
+ {
+ temp = burst[i];
+ burst[i] = burst[i + 1];
+ burst[i + 1] = temp;
+ }
+
+ memcpy (burst, &ac3p, sizeof(struct AC3PREAMBLE));
+
+ fwrite (burst, 1, 6144, outfile);
+
+ }
+
+ printf ("Last Sampleratecode: %i\n", sampleratecode);
+
+ wavhdr.SubChunk2Size = (ftell(outfile) - 44);
+ wavhdr.ChunkSize = wavhdr.SubChunk2Size + 36;
+
+ fseek (outfile, SEEK_SET, 0);
+ fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);
+
+ fclose (infile);
+ fclose (outfile);
+
+ return 0;
+}
diff --git a/dts2spdif.c b/dts2spdif.c
new file mode 100755
index 0000000..6aa15bb
--- /dev/null
+++ b/dts2spdif.c
@@ -0,0 +1,177 @@
+
+#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+#include <memory.h>
+
+struct WAVEHEADER {
+ unsigned long ChunkID;
+ unsigned long ChunkSize;
+ unsigned long Format;
+ unsigned long SubChunk1ID;
+ unsigned long SubChunk1Size;
+ unsigned short AudioFormat;
+ unsigned short NumChannels;
+ unsigned long SampleRate;
+ unsigned long ByteRate;
+ unsigned short BlockAlign;
+ unsigned short BitsPerSample;
+ unsigned long SubChunk2ID;
+ unsigned long SubChunk2Size;
+};
+
+
+unsigned char burst[6144];
+
+FILE *infile, *outfile;
+
+unsigned long bytesread;
+unsigned long pcmbytes;
+unsigned long pcmbytesmultiplier;
+char sampleratecode;
+unsigned long framesize;
+
+struct WAVEHEADER wavhdr = { 0x46464952,
+ 0,
+ 0x45564157,
+ 0x20746D66,
+ 16,
+ 1,
+ 2,
+ 0,
+ 0,
+ 4,
+ 16,
+ 0x61746164,
+ 0 };
+
+unsigned long i;
+char temp;
+
+int main( int argc, char *argv[ ], char *envp[ ] )
+{
+ if (argc < 3)
+ {
+ printf("Wrong syntax. dts2spdif <In.dts> <Out.wav>.\n");
+ return 0;
+ }
+
+ infile = fopen(argv[1], "rb");
+ outfile = fopen(argv[2], "wb");
+ //fseek(outfile, SEEK_SET, 44);
+ fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);
+
+
+ for(;;)
+ {
+ memset (burst, 0, 6144);
+ bytesread = fread(burst, 1, 9, infile);
+ if (bytesread < 9)
+ {
+ printf ("EOF reached (Frame Header reading)!\nCurrent position in INFILE: %i\n", ftell(infile));
+ break;
+ }
+ if (((unsigned long*)burst)[0] != 0x0180fe7f)
+ {
+ printf("ERROR: INVALID SYNCWORD !\nCurrent position in INFILE: %i\n", ftell(infile));
+ break;
+ }
+ framesize = (burst[5] & 3);
+ framesize = framesize * 4096;
+ framesize = framesize + (burst[6] * 16);
+ framesize = framesize + ((burst[7] & 240) / 16);
+ framesize = framesize + 1;
+
+ sampleratecode = ((burst[8] & 60) / 4);
+
+ if (wavhdr.SampleRate == 0)
+ {
+ printf ("First Sampleratecode: %i\n", sampleratecode);
+
+ switch (sampleratecode)
+ {
+ case 1:
+ pcmbytesmultiplier = 4;
+ case 2:
+ pcmbytesmultiplier = 2;
+ case 3:
+ pcmbytesmultiplier = 1;
+ wavhdr.SampleRate = 32000;
+ wavhdr.ByteRate = 128000;
+ break;
+ case 6:
+ pcmbytesmultiplier = 4;
+ case 7:
+ pcmbytesmultiplier = 2;
+ case 8:
+ pcmbytesmultiplier = 1;
+ wavhdr.SampleRate = 44100;
+ wavhdr.ByteRate = 176000;
+ break;
+ case 11:
+ pcmbytesmultiplier = 4;
+ case 12:
+ pcmbytesmultiplier = 2;
+ case 13:
+ pcmbytesmultiplier = 1;
+ wavhdr.SampleRate = 48000;
+ wavhdr.ByteRate = 192000;
+ break;
+ default:
+ wavhdr.SampleRate = 0;
+ wavhdr.ByteRate = 0;
+ printf ("Invalid Sampleratecode ! Aborting process...\n");
+ break;
+ }
+ }
+
+ pcmbytes = (burst[4] & 1);
+ pcmbytes = pcmbytes * 64;
+ pcmbytes = pcmbytes + ((burst[5] & 252) / 4);
+ pcmbytes = pcmbytes + 1;
+ pcmbytes = pcmbytes * 128;
+ pcmbytes = pcmbytes * pcmbytesmultiplier;
+
+
+ bytesread = fread (&burst[9], 1, framesize - 9, infile);
+ if ((bytesread + 9) < framesize)
+ {
+ printf ("EOF reached (Burst Reading)!\nCurrent position in INFILE: %i\n", ftell(infile));
+ printf ("Frame size: %i .. Bytes read: %i\n", framesize, bytesread);
+ break;
+ }
+
+ for (i = 0; i < framesize; i += 2)
+ {
+ temp = burst[i];
+ burst[i] = burst[i + 1];
+ burst[i + 1] = temp;
+ }
+
+
+ fwrite (burst, 1, framesize, outfile);
+ if (pcmbytes > framesize)
+ {
+ fwrite ("", 1, pcmbytes - framesize, outfile);
+ }
+ else
+ {
+ printf("Warning: Frame Size > LPCM Frame Size! Buffer underrun may occur/File damaged?\n");
+ printf("Frame start at INFILE Offset: %i\n", ftell(infile) - framesize);
+ }
+ }
+
+ printf ("Last Sampleratecode: %i\n", sampleratecode);
+
+ wavhdr.SubChunk2Size = (ftell(outfile) - 44);
+ wavhdr.ChunkSize = wavhdr.SubChunk2Size + 36;
+
+ fseek (outfile, SEEK_SET, 0);
+ fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);
+
+
+ fclose (infile);
+ fclose (outfile);
+
+ return 0;
+}