Skip to content

Instantly share code, notes, and snippets.

@nekno
Created March 26, 2022 00:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekno/594cf46a8c58e32b382ffbca37a7fb4e to your computer and use it in GitHub Desktop.
Save nekno/594cf46a8c58e32b382ffbca37a7fb4e to your computer and use it in GitHub Desktop.
thdmerge modded for stdin
#define _CRT_SECURE_NO_WARNINGS
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
void write_frame(unsigned char* buf, int len, int fd)
{
int status;
if ((status = _write(fd, buf, len)) != len)
{
switch (errno)
{
case EBADF:
perror("Bad file descriptor!");
break;
case ENOSPC:
perror("No space left on device!");
break;
case EINVAL:
perror("Invalid parameter: buffer was NULL!");
break;
default:
break;
}
}
}
int next_ac3(unsigned char *buf, int ac3_fd, int out_fd)
{
int fsize;
if (_eof(ac3_fd))
return -1;
// Determine the frame size to write.
if (_read(ac3_fd, buf, 8) != 8)
return -1;
switch (buf[4] & 0b00111110)
{
case 0b001000:
fsize = 2 * 128;
break;
case 0b001010:
fsize = 2 * 160;
break;
case 0b001100:
fsize = 2 * 192;
break;
case 0b001110:
fsize = 2 * 224;
break;
case 0b010000:
fsize = 2 * 256;
break;
case 0b010010:
fsize = 2 * 320;
break;
case 0b010100:
fsize = 2 * 384;
break;
case 0b010110:
fsize = 2 * 448;
break;
case 0b011000:
fsize = 2 * 512;
break;
case 0b011010:
fsize = 2 * 640;
break;
case 0b011100:
fsize = 2 * 768;
break;
case 0b011110:
fsize = 2 * 896;
break;
case 0b100000:
fsize = 2 * 1024;
break;
case 0b100010:
fsize = 2 * 1152;
break;
case 0b100100:
fsize = 2 * 1280;
break;
default:
return -1;
}
// Write the frame.
if (_lseeki64(ac3_fd, -8, SEEK_CUR) == -1L)
return -1;
if (_read(ac3_fd, buf, fsize) != fsize)
return -1;
write_frame(buf, fsize, out_fd);
return 0;
}
int next_truehd(unsigned char *buf, int truehd_fd, int out_fd)
{
int length, bytes_read = 0, total_bytes = 0, header_size = 8;
// Determine the frame size to write.
while (total_bytes < header_size)
{
bytes_read = _read(truehd_fd, &buf[total_bytes], header_size-total_bytes);
//printf("Header bytes read: %d\n", bytes_read);
if (bytes_read == 0)
return -1;
total_bytes += bytes_read;
}
length = (2 * (((buf[0] << 8) | (buf[1])) & 0xfff));
//printf("Length: %d\n", length);
// Write the frame.
while (total_bytes < length)
{
bytes_read = _read(truehd_fd, &buf[total_bytes], length-total_bytes);
//printf("Bytes read: %d\n", bytes_read);
if (bytes_read == 0)
return -1;
total_bytes += bytes_read;
}
write_frame(buf, length, out_fd);
return 0;
}
void print_usage()
{
printf("thdmerge 1.1+ by Donald A. Graft, modded by nekno\n");
printf("Usage: thdmerge [-thd thd_file] -ac3 ac3_file -o output_file [-t]\n");
printf("-thd: path to the TrueHD file; if omitted, the TrueHD stream can be provided on standard input\n");
printf("-ac3: path to the AC3 file\n");
printf("-o : path to the interleaved .thd+ac3 output file\n");
printf("-t : truncate longer stream to length of shorter stream\n");
exit(0);
}
int main(int argc, char** argv)
{
unsigned char *buf;
double truehd_time, ac3_time;
int stdin_fd = -1, truehd_fd = -1, ac3_fd = -1, out_fd = -1;
int ac3_eof, truehd_eof;
int truncate = 0;
int arg;
if (argc < 5 || argc > 8)
print_usage();
for (arg = 1; arg < argc; arg++)
{
if (strcmp(argv[arg], "-thd") == 0)
{
truehd_fd = _open(argv[++arg], _O_BINARY);
if (truehd_fd == -1)
{
printf("Cannot open TrueHD file\n");
exit(0);
}
}
else if (strcmp(argv[arg], "-ac3") == 0)
{
ac3_fd = _open(argv[++arg], _O_BINARY);
if (ac3_fd == -1)
{
printf("Cannot open AC3 file\n");
exit(0);
}
}
else if (strcmp(argv[arg], "-o") == 0)
{
_unlink(argv[++arg]);
out_fd = _open(argv[arg], _O_WRONLY | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE);
if (out_fd == -1)
{
printf("Cannot open output file\n");
exit(0);
}
}
else if (strcmp(argv[arg], "-t") == 0)
{
truncate = 1;
}
}
if (truehd_fd == -1)
{
freopen(NULL, "rb", stdin);
stdin_fd = _fileno(stdin);
if (_setmode(stdin_fd, _O_BINARY) == -1)
{
printf("thdmerge: could not read standard input in binary mode\n");
exit(1);
}
truehd_fd = stdin_fd;
printf("Reading TrueHD stream from standard input\n");
}
if (ac3_fd == -1 || out_fd == -1)
print_usage();
buf = (unsigned char*)malloc(1024 * 1024);
if (buf == NULL)
{
printf("thdmerge: could not allocate memory\n");
exit(1);
}
ac3_time = truehd_time = 0;
ac3_eof = truehd_eof = 0;
// Interleave keeping sync.
// Keep going until both streams hit EOF.
while (1)
{
if (ac3_eof && truehd_eof)
break;
if (!ac3_eof && (truehd_eof || ac3_time <= truehd_time))
{
if (next_ac3(buf, ac3_fd, out_fd) == -1)
{
ac3_eof = 1;
if (truncate)
break;
}
else
ac3_time += 0.032f;
}
else
{
if (next_truehd(buf, truehd_fd, out_fd) == -1)
{
truehd_eof = 1;
if (truncate)
break;
}
else
truehd_time += 1.0f / 1200;
}
}
free(buf);
_close(truehd_fd);
_close(ac3_fd);
_close(out_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment