Initial commit.
authornorly <ny-git@enpas.org>
Sat, 29 Oct 2011 17:59:57 +0000 (18:59 +0100)
committernorly <ny-git@enpas.org>
Sat, 29 Oct 2011 17:59:57 +0000 (18:59 +0100)
Basically the old code from 2006/07, slightly
modified to compile on modern GCC/Linux.
Changed the tool names.

.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
ac32spdif.c [new file with mode: 0755]
dts2spdif.c [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..3c6e429
--- /dev/null
@@ -0,0 +1,2 @@
+ac32spdif
+dts2spdif
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
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 (executable)
index 0000000..a1ab79f
--- /dev/null
@@ -0,0 +1,182 @@
+\r
+#include <stdio.h>\r
+//#include <stdlib.h>\r
+//#include <string.h>\r
+#include <memory.h>\r
+\r
+//#include "fs_codes.h"\r
+\r
+\r
+short bitrates[] = { 32,  40,  48,  56,  64,  80,  96, 112, 128, 160,\r
+192, 224, 256, 320, 384, 448, 512, 576, 640 };\r
+\r
+short fsize44[] = {  70,   88,  105,  122,  140,  175,  209,  244,  279,  349,\r
+418,  488,  558,  697,  836,  976, 1115, 1254, 1394 };\r
+\r
+unsigned long DecFS(char sratecode, unsigned long fsizecode)\r
+{\r
+       switch (sratecode)\r
+       {\r
+               case 0:\r
+                       return (bitrates[fsizecode / 2] * 2);\r
+               case 1:\r
+                       return ((fsizecode % 2) ? fsize44[fsizecode / 2] : fsize44[fsizecode / 2] - 1);\r
+               case 2:\r
+                       return (bitrates[fsizecode / 2] * 3);\r
+               default:\r
+                       return 0;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+\r
+\r
+struct WAVEHEADER {\r
+    unsigned long  ChunkID;\r
+    unsigned long  ChunkSize;\r
+    unsigned long  Format;\r
+    unsigned long  SubChunk1ID;\r
+    unsigned long  SubChunk1Size;\r
+    unsigned short AudioFormat;\r
+    unsigned short NumChannels;\r
+    unsigned long  SampleRate;\r
+    unsigned long  ByteRate;\r
+    unsigned short BlockAlign;\r
+    unsigned short BitsPerSample;\r
+    unsigned long  SubChunk2ID;\r
+    unsigned long  SubChunk2Size;\r
+};\r
+\r
+\r
+struct AC3PREAMBLE {\r
+       unsigned short sync1;\r
+       unsigned short sync2;\r
+       unsigned char burst_infoLSB;\r
+       unsigned char burst_infoMSB;\r
+       unsigned short lengthcode;\r
+};\r
+\r
+char burst[6144];\r
+\r
+FILE *infile, *outfile;\r
+\r
+unsigned long bytesread;\r
+unsigned long payloadbytes;\r
+char sampleratecode;\r
+unsigned long framesizecode;\r
+\r
+struct AC3PREAMBLE ac3p = { 0xF872, 0x4E1F, 1, 0, 0x3800 };\r
+struct WAVEHEADER wavhdr = { 0x46464952,\r
+                                                       0,\r
+                                                       0x45564157,\r
+                                                       0x20746D66,\r
+                                                       16,\r
+                                                       1,\r
+                                                       2,\r
+                                                       0,\r
+                                                       0,\r
+                                                       4,\r
+                                                       16,\r
+                                                       0x61746164,\r
+                                                       0 };\r
+\r
+unsigned long i;\r
+char temp;\r
+\r
+int main( int argc, char *argv[ ], char *envp[ ] )\r
+{\r
+       if (argc < 3)\r
+       {\r
+               printf("Wrong syntax. AC3PACK <In.ac3> <Out.wav>.\n");\r
+               return 0;\r
+       }\r
+\r
+       infile = fopen(argv[1], "rb");\r
+       outfile = fopen(argv[2], "wb");\r
+       //fseek(outfile, SEEK_SET, 44);\r
+       fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);\r
+\r
+\r
+\r
+       for(;;)\r
+       {\r
+               memset (burst, 0, 6144);\r
+               bytesread = fread(&burst[8], 1, 6, infile);\r
+               if (bytesread < 6)\r
+               {\r
+                       printf ("EOF reached (Frame Header reading)!\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       break;\r
+               }\r
+               if ((burst[8] != 0x0B) || (burst[9] != 0x77))\r
+               {\r
+                       printf("ERROR: INVALID SYNCWORD !\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       break;\r
+               }\r
+               framesizecode = (burst[12] & 63);\r
+               sampleratecode = ((burst[12] & 192) / 64);\r
+\r
+               if (wavhdr.SampleRate == 0)\r
+               {\r
+                               printf ("First Sampleratecode: %i\n", sampleratecode);\r
+\r
+                               switch (sampleratecode)\r
+                               {\r
+                               case 0:\r
+                                       wavhdr.SampleRate = 48000;\r
+                                       wavhdr.ByteRate = 192000;\r
+                                       break;\r
+                               case 1:\r
+                                       wavhdr.SampleRate = 44100;\r
+                                       wavhdr.ByteRate = 176000;\r
+                                       break;\r
+                               case 2:\r
+                                       wavhdr.SampleRate = 32000;\r
+                                       wavhdr.ByteRate = 128000;\r
+                                       break;\r
+                               default:\r
+                                       wavhdr.SampleRate = 48000;\r
+                                       wavhdr.ByteRate = 192000;\r
+                               }\r
+               }\r
+\r
+               payloadbytes = DecFS (sampleratecode, framesizecode);\r
+               payloadbytes *= 2;\r
+\r
+               bytesread = fread (&burst[14], 1, payloadbytes - 6, infile);\r
+               if ((bytesread + 6) < payloadbytes)\r
+               {\r
+                       printf ("EOF reached (Burst Reading)!\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       printf ("Frame size: %i  .. Bytes read: %i\n", payloadbytes, bytesread);\r
+                       break;\r
+               }\r
+               ac3p.burst_infoMSB = (burst[13] & 7);\r
+               ac3p.lengthcode = (short)(payloadbytes * 8);\r
+\r
+               for (i = 8; i < (payloadbytes + 8); i += 2)\r
+               {\r
+                       temp = burst[i];\r
+                       burst[i] = burst[i + 1];\r
+                       burst[i + 1] = temp;\r
+               }\r
+\r
+               memcpy (burst, &ac3p, sizeof(struct AC3PREAMBLE));\r
+\r
+               fwrite (burst, 1, 6144, outfile);\r
+\r
+       }\r
+\r
+       printf ("Last Sampleratecode: %i\n", sampleratecode);\r
+\r
+       wavhdr.SubChunk2Size = (ftell(outfile) - 44);\r
+       wavhdr.ChunkSize = wavhdr.SubChunk2Size + 36;\r
+\r
+       fseek (outfile, SEEK_SET, 0);\r
+       fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);\r
+\r
+       fclose (infile);\r
+       fclose (outfile);\r
+\r
+       return 0;\r
+}\r
diff --git a/dts2spdif.c b/dts2spdif.c
new file mode 100755 (executable)
index 0000000..6aa15bb
--- /dev/null
@@ -0,0 +1,177 @@
+\r
+#include <stdio.h>\r
+//#include <stdlib.h>\r
+//#include <string.h>\r
+#include <memory.h>\r
+\r
+struct WAVEHEADER {\r
+    unsigned long  ChunkID;\r
+    unsigned long  ChunkSize;\r
+    unsigned long  Format;\r
+    unsigned long  SubChunk1ID;\r
+    unsigned long  SubChunk1Size;\r
+    unsigned short AudioFormat;\r
+    unsigned short NumChannels;\r
+    unsigned long  SampleRate;\r
+    unsigned long  ByteRate;\r
+    unsigned short BlockAlign;\r
+    unsigned short BitsPerSample;\r
+    unsigned long  SubChunk2ID;\r
+    unsigned long  SubChunk2Size;\r
+};\r
+\r
+\r
+unsigned char burst[6144];\r
+\r
+FILE *infile, *outfile;\r
+\r
+unsigned long bytesread;\r
+unsigned long pcmbytes;\r
+unsigned long pcmbytesmultiplier;\r
+char sampleratecode;\r
+unsigned long framesize;\r
+\r
+struct WAVEHEADER wavhdr = { 0x46464952,\r
+                                                       0,\r
+                                                       0x45564157,\r
+                                                       0x20746D66,\r
+                                                       16,\r
+                                                       1,\r
+                                                       2,\r
+                                                       0,\r
+                                                       0,\r
+                                                       4,\r
+                                                       16,\r
+                                                       0x61746164,\r
+                                                       0 };\r
+\r
+unsigned long i;\r
+char temp;\r
+\r
+int main( int argc, char *argv[ ], char *envp[ ] )\r
+{\r
+       if (argc < 3)\r
+       {\r
+               printf("Wrong syntax. dts2spdif <In.dts> <Out.wav>.\n");\r
+               return 0;\r
+       }\r
+\r
+       infile = fopen(argv[1], "rb");\r
+       outfile = fopen(argv[2], "wb");\r
+       //fseek(outfile, SEEK_SET, 44);\r
+       fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);\r
+\r
+\r
+       for(;;)\r
+       {\r
+               memset (burst, 0, 6144);\r
+               bytesread = fread(burst, 1, 9, infile);\r
+               if (bytesread < 9)\r
+               {\r
+                       printf ("EOF reached (Frame Header reading)!\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       break;\r
+               }\r
+               if (((unsigned long*)burst)[0] != 0x0180fe7f)\r
+               {\r
+                       printf("ERROR: INVALID SYNCWORD !\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       break;\r
+               }\r
+               framesize = (burst[5] & 3);\r
+               framesize = framesize * 4096;\r
+               framesize = framesize + (burst[6] * 16);\r
+               framesize = framesize + ((burst[7] & 240) / 16);\r
+               framesize = framesize + 1;\r
+\r
+               sampleratecode = ((burst[8] & 60) / 4);\r
+\r
+               if (wavhdr.SampleRate == 0)\r
+               {\r
+                               printf ("First Sampleratecode: %i\n", sampleratecode);\r
+\r
+                               switch (sampleratecode)\r
+                               {\r
+                               case 1:\r
+                                       pcmbytesmultiplier = 4;\r
+                               case 2:\r
+                                       pcmbytesmultiplier = 2;\r
+                               case 3:\r
+                                       pcmbytesmultiplier = 1;\r
+                                       wavhdr.SampleRate = 32000;\r
+                                       wavhdr.ByteRate = 128000;\r
+                                       break;\r
+                               case 6:\r
+                                       pcmbytesmultiplier = 4;\r
+                               case 7:\r
+                                       pcmbytesmultiplier = 2;\r
+                               case 8:\r
+                                       pcmbytesmultiplier = 1;\r
+                                       wavhdr.SampleRate = 44100;\r
+                                       wavhdr.ByteRate = 176000;\r
+                                       break;\r
+                               case 11:\r
+                                       pcmbytesmultiplier = 4;\r
+                               case 12:\r
+                                       pcmbytesmultiplier = 2;\r
+                               case 13:\r
+                                       pcmbytesmultiplier = 1;\r
+                                       wavhdr.SampleRate = 48000;\r
+                                       wavhdr.ByteRate = 192000;\r
+                                       break;\r
+                               default:\r
+                                       wavhdr.SampleRate = 0;\r
+                                       wavhdr.ByteRate = 0;\r
+                                       printf ("Invalid Sampleratecode ! Aborting process...\n");\r
+                                       break;\r
+                               }\r
+               }\r
+\r
+               pcmbytes = (burst[4] & 1);\r
+               pcmbytes = pcmbytes * 64;\r
+               pcmbytes = pcmbytes + ((burst[5] & 252) / 4);\r
+               pcmbytes = pcmbytes + 1;\r
+               pcmbytes = pcmbytes * 128;\r
+               pcmbytes = pcmbytes * pcmbytesmultiplier;\r
+\r
+\r
+               bytesread = fread (&burst[9], 1, framesize - 9, infile);\r
+               if ((bytesread + 9) < framesize)\r
+               {\r
+                       printf ("EOF reached (Burst Reading)!\nCurrent position in INFILE: %i\n", ftell(infile));\r
+                       printf ("Frame size: %i  .. Bytes read: %i\n", framesize, bytesread);\r
+                       break;\r
+               }\r
+\r
+               for (i = 0; i < framesize; i += 2)\r
+               {\r
+                       temp = burst[i];\r
+                       burst[i] = burst[i + 1];\r
+                       burst[i + 1] = temp;\r
+               }\r
+\r
+\r
+               fwrite (burst, 1, framesize, outfile);\r
+               if (pcmbytes > framesize)\r
+               {\r
+                       fwrite ("", 1, pcmbytes - framesize, outfile);\r
+               }\r
+               else\r
+               {\r
+                       printf("Warning: Frame Size > LPCM Frame Size! Buffer underrun may occur/File damaged?\n");\r
+                       printf("Frame start at INFILE Offset: %i\n", ftell(infile) - framesize);\r
+               }\r
+       }\r
+\r
+       printf ("Last Sampleratecode: %i\n", sampleratecode);\r
+\r
+       wavhdr.SubChunk2Size = (ftell(outfile) - 44);\r
+       wavhdr.ChunkSize = wavhdr.SubChunk2Size + 36;\r
+\r
+       fseek (outfile, SEEK_SET, 0);\r
+       fwrite (&wavhdr, sizeof(struct WAVEHEADER), 1, outfile);\r
+\r
+\r
+       fclose (infile);\r
+       fclose (outfile);\r
+\r
+       return 0;\r
+}\r