Created
November 20, 2020 02:30
-
-
Save ericek111/abe5829f6e52e4b25b3b97a0efd0b22b to your computer and use it in GitHub Desktop.
CS:GO voice demo parser
This file contains hidden or 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
#include <unistd.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <sys/time.h> | |
#include <celt.h> | |
// gcc -o csgo csgo.c -I./celt-0.11.1/libcelt -L"$HOME/.steam/steam/steamapps/common/Counter-Strike Global Offensive/bin/linux64" -l:vaudio_celt_client.so && ./csgo && play -t raw -r 22050 -e signed -b 16 -c 1 out.raw | |
// export LD_LIBRARY_PATH="$HOME/.steam/steam/steamapps/common/Counter-Strike Global Offensive/bin/linux64" | |
// ./csgo | |
// play -t raw -r 22050 -e signed -b 16 -c 1 out.raw | |
// sox -t raw -r 22050 -e signed -b 16 -c 1 -L out.raw out.wav | |
#define BUF_SIZE 1024*1024 | |
int main(int argc, char *argv[]) { | |
unsigned char buf[BUF_SIZE]; | |
const unsigned int FRAME_SIZE = 512; | |
const unsigned int SAMPLE_RATE = 22050; | |
FILE *f = fopen("voicedata.dat", "r"); | |
if (f == NULL) { | |
return 1; | |
} | |
size_t read = fread(buf, 1, BUF_SIZE, f); | |
fclose(f); | |
CELTMode *dm = celt_mode_create(SAMPLE_RATE, FRAME_SIZE, NULL); | |
CELTDecoder *d = celt_decoder_create_custom(dm, 1, NULL); | |
size_t outsize = (read / 64) * FRAME_SIZE * sizeof(celt_int16); | |
celt_int16* pcmout = malloc(outsize); | |
size_t done = 0; | |
int frames = 0; | |
for (; done < read; done += 64, frames++) { | |
int ret = 0; | |
if ((ret = celt_decode(d, buf + done, 64, pcmout + frames * FRAME_SIZE, FRAME_SIZE)) < 0) { | |
fprintf(stderr, "unable to decode... > %d (at %d/%d)\n", ret, done, read); | |
//return 1; | |
} | |
//printf("Done %d/%d (to %ld/%ld)\n", done, read, frames * FRAME_SIZE * 2, outsize); | |
} | |
FILE* file_p = fopen("out.raw", "w"); | |
size_t written = fwrite(pcmout, outsize, 1, file_p); | |
fclose(file_p); | |
free(pcmout); | |
return 0; | |
} |
So you can just "insert" the audio into the .dem file by just reversing this one process? How come noone ever thought of that?
Maybe no one ever needed it. ¯_(ツ)_/¯ Anyway, here it is: https://github.com/ericek111/GODemolyser/blob/master/GODemolyser/src/eu/lixko/godemolyser/codec/VoiceWriter.java
And here's a demo produced by that abomination: https://drive.google.com/file/d/1Lyo6cPh1ps_BVXDwxcD5jty7l25MU42Z/view?usp=sharing
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Actually, maybe it's not that hard. Look at my GODemolyser, even lacking lots of features, it's still the most understandable to me (and also the fastest). You could inject your own dem_packet-s into the file. Protobufs can be, just as easily as they are parsed, constructed from your own data. Here, basically revert this process: https://github.com/ericek111/GODemolyser/blob/master/GODemolyser/src/eu/lixko/godemolyser/parser/dem/PacketParser.java#L15
I think the greatest hurdle here would be implementing write support for the ByteArrayDataStream class, hah. It operates without copying, so inserting data mid-buffer would shift other data and mess up all slices created from it. Some things are also bit-indexed (Protobuf encoding), so the entire affected buffer would have to be bit-shifted on non-aligned writes. But, from what I recall, packets are aligned to bytes, to that shouldn't be an issue for your use case, just thinking aloud. Also, the
DataStream
class (from which implementations are extended) does not care about the underlying storage.