--- /dev/null
+ac32spdif
+dts2spdif
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+\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
--- /dev/null
+\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