Last active
May 9, 2021 00:15
-
-
Save Zinfidel/aa682eb9e19ab22f297ab23146f5018a to your computer and use it in GitHub Desktop.
Opus original sample tag replacer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See RFC 3533 for ogg header format (https://tools.ietf.org/html/rfc3533#section-6) | |
// See RFC 7845 for opus header format (https://tools.ietf.org/html/rfc7845#section-5) | |
#include <stdio.h> | |
#include <string.h> | |
#include "osample.h" | |
static word32 crc_table[256]; // Table of 8-bit remainders for crc | |
int main(int argc, char* argv[]) { | |
// Argument parsing | |
if (argc < 3) | |
return -1; | |
const char* filename = argv[1]; | |
int origRate = strtoul(argv[2], NULL, 10); | |
if (origRate == 0 || origRate == LONG_MIN || origRate == LONG_MAX) | |
return -1; | |
FILE* fp; | |
fopen_s(&fp, filename, "r+b"); | |
if (fp == NULL) | |
return -1; | |
// Read ogg header page up to page segment count. | |
byte headerPage[PAGE_BUFFER_SIZE] = { 0 }; | |
byte* pagePtr = headerPage; | |
size_t bytesToRead = OGG_PSEGS_OFFSET + 1; | |
size_t bytesRead = 0; | |
bytesRead = fread_s(pagePtr, sizeof(headerPage), sizeof(byte), bytesToRead, fp); | |
pagePtr += bytesRead; | |
if (bytesRead != bytesToRead) | |
return -1; | |
// Read segment lacing values to figure out total page size. | |
int pageSegments = headerPage[OGG_PSEGS_OFFSET]; | |
size_t headerSize = OGG_STATIC_SIZE + pageSegments; | |
bytesRead = fread_s(pagePtr, sizeof(headerPage) - bytesRead, sizeof(byte), pageSegments, fp); | |
if (bytesRead != pageSegments) | |
return -1; | |
size_t pageSize = headerSize; | |
for (int i = 0; i < pageSegments; i++) | |
pageSize += *pagePtr++; | |
// Read the rest of the header and page content, and check that we got the Opus page. | |
bytesToRead = pageSize - headerSize; | |
if ((sizeof(headerPage) - headerSize) < bytesToRead) | |
return -1; // Not sure how a header could be this big but it's technically possible. | |
bytesRead = fread_s(pagePtr, sizeof(headerPage) - headerSize, sizeof(byte), bytesToRead, fp); | |
if (bytesRead != bytesToRead) | |
return -1; | |
char opusMagicString[9] = { 0 }; | |
errno_t err = strncpy_s(opusMagicString, 9, headerPage + headerSize, 8); | |
if (err != 0 || strcmp(opusMagicString, "OpusHead") != 0) | |
return -1; | |
// Set the original frequency, calculate CRC, write out to file. | |
*((word32*)(headerPage + OGG_CRC_OFFSET)) = 0x00000000; | |
*((word32*)(pagePtr + OPUS_ORIGSAMP_OFFSET)) = host_to_le_ulong(origRate); | |
gen_crc_table(); | |
word32 crc = update_crc(0, headerPage, pageSize); | |
word32 outBuf[2] = { host_to_le_ulong(crc), host_to_le_ulong(origRate) }; | |
fseek(fp, OGG_CRC_OFFSET, SEEK_SET); | |
fwrite(&outBuf[0], sizeof(word32), 1, fp); | |
fseek(fp, headerSize + OPUS_ORIGSAMP_OFFSET, SEEK_SET); | |
fwrite(&outBuf[1], sizeof(word32), 1, fp); | |
fclose(fp); | |
return 0; | |
} | |
void gen_crc_table(void) | |
{ | |
register word16 i, j; | |
register word32 crc_accum; | |
for (i = 0; i < 256; i++) | |
{ | |
crc_accum = ((word32)i << 24); | |
for (j = 0; j < 8; j++) | |
{ | |
if (crc_accum & 0x80000000L) | |
crc_accum = (crc_accum << 1) ^ POLYNOMIAL; | |
else | |
crc_accum = (crc_accum << 1); | |
} | |
crc_table[i] = crc_accum; | |
} | |
} | |
word32 update_crc(word32 crc_accum, byte* data_blk_ptr, word32 data_blk_size) | |
{ | |
register word32 i, j; | |
for (j = 0; j < data_blk_size; j++) | |
{ | |
i = ((int)(crc_accum >> 24) ^ *data_blk_ptr++) & 0xFF; | |
crc_accum = (crc_accum << 8) ^ crc_table[i]; | |
} | |
//crc_accum = ~crc_accum; | |
return crc_accum; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <Windows.h> | |
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN | |
# define host_to_le_ulong(VAL) VAL | |
#else | |
# define host_to_le_ulong(VAL) _byteswap_ulong(VAL) | |
#endif | |
#define PAGE_BUFFER_SIZE 2048 | |
#define OGG_STATIC_SIZE 27 | |
#define OGG_CRC_OFFSET 22 | |
#define OGG_PSEGS_OFFSET 26 | |
#define OPUS_ORIGSAMP_OFFSET 12 | |
#define POLYNOMIAL 0x04c11db7L // Standard CRC-32 ppolynomial | |
typedef unsigned char byte; // Byte is a char | |
typedef unsigned short int word16; // 16-bit word is a short int | |
typedef unsigned int word32; // 32-bit word is an int | |
void gen_crc_table(void); | |
word32 update_crc(word32 crc_accum, byte* data_blk_ptr, word32 data_blk_size); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment