cuticle/hi/opus.c
2024-06-30 14:43:13 +03:00

86 lines
2.4 KiB
C

#include"node.h"
#include<opus.h>
#include<string.h>
#include"img.h"
#include<stdlib.h>
#include<stdio.h>
struct CHiEncodeOpusNode {
CHiPubNode pubn;
size_t pcmSamples, pcmCapacity;
int16_t *pcmbuf;
size_t timestamp;
OpusEncoder *enc;
};
static int encodeopus_perform(CHiPubNode *pubn) {
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
CHiImage *newpcm = CHi_Crawl(&pubn->sinks[0])->data.sample;
if(n->pcmSamples + newpcm->width > n->pcmCapacity) {
n->pcmbuf = realloc(n->pcmbuf, sizeof(*n->pcmbuf) * (n->pcmCapacity = ((n->pcmSamples + newpcm->width + 1023) & ~1023)));
}
memcpy(&n->pcmbuf[n->pcmSamples], newpcm->data16, sizeof(*n->pcmbuf) * newpcm->width);
n->pcmSamples += newpcm->width;
CHiBSFrames *frames = malloc(sizeof(*frames));
frames->count = 0;
size_t samp;
for(samp = 0; samp + 960 <= n->pcmSamples; samp += 960) {
frames = realloc(frames, sizeof(*frames) + sizeof(*frames->data) * (frames->count + 1));
frames->data[frames->count].timestamp = n->timestamp;
frames->data[frames->count].ptr = malloc(1276);
frames->data[frames->count].sz = opus_encode(n->enc, &n->pcmbuf[samp], 960, frames->data[frames->count].ptr, 1276);
if(frames->data[frames->count].sz < 0) puts("OPUS ERR");
frames->count++;
n->timestamp += 20;
}
memmove(n->pcmbuf, n->pcmbuf + samp, sizeof(*n->pcmbuf) * (n->pcmSamples - samp));
n->pcmSamples -= samp;
pubn->sources[0].type = CUTIHI_VAL_OPUSBS;
pubn->sources[0].data.bitstream = frames;
return 1;
}
CUTIVIS CHiPubNode *CHi_EncodeOpus() {
struct CHiEncodeOpusNode *ret = calloc(1, sizeof(*ret));
ret->pubn.type = CUTIHI_T('CEnc','Opus');
ret->pubn.Start = CHi_EncodeOpus_Start;
ret->pubn.Perform = &encodeopus_perform;
ret->pubn.Stop = CHi_EncodeOpus_Stop;
ret->pubn.clean = 0;
ret->pubn.sinks = calloc(sizeof(*ret->pubn.sinks), ret->pubn.sinkCount = 1);
ret->pubn.sources = calloc(sizeof(*ret->pubn.sources), ret->pubn.sourceCount = 1);
return &ret->pubn;
}
CUTIVIS int CHi_EncodeOpus_Start(CHiPubNode *pubn) {
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
int error;
n->enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &error);
n->pcmSamples = 0;
n->pcmCapacity = 1024;
n->pcmbuf = malloc(sizeof(*n->pcmbuf) * n->pcmCapacity);
n->timestamp = 0;
return 1;
}
CUTIVIS int CHi_EncodeOpus_Stop(CHiPubNode *pubn) {
struct CHiEncodeOpusNode *n = (struct CHiEncodeOpusNode*) pubn;
opus_encoder_destroy(n->enc);
free(n->pcmbuf);
return 1;
}