#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "celt.h"
int

main(int argc, char **argv)
{

char data[2048] =
{ };

short pcm[2048] =
{ };
int rate = 48000;
int framesize = 960;
int channels = 1;
int tmp;
int rem;
void *mode;
void *state;
uint16_t len;

while ((tmp = getopt(argc, argv, "r:f:c:")) != -1)
{

switch (tmp)
{
case 'r':
rate = atoi(optarg);
break;
case 'f':
framesize = atoi(optarg);
break;
case 'c':
channels = atoi(optarg);
break;
}
}

if (!(mode = celt_mode_create(rate, framesize, &tmp)))
{
fprintf(stderr, "error: celt_mode_create: %s\n", celt_strerror(tmp));
return 1;
}

if (!(state = celt_decoder_create_custom(mode, channels, &tmp)))
{
fprintf(stderr, "error: celt_decoder_create_custom: %s\n", celt_strerror(tmp));
celt_mode_destroy(mode);
return 1;
}

for (len = 0;;)
{

if (!len)
{

if (read(STDIN_FILENO, &len, sizeof(len)) != sizeof(len))
{
break;
}

if (len > sizeof(data))
{
fprintf(stderr, "error: celt packet larger than buffer\n");
celt_decoder_destroy(state);
celt_mode_destroy(mode);
return 1;
}
rem = len;
}

if ((tmp = read(STDIN_FILENO, data + (len - rem), rem)) < 0)
{
fprintf(stderr, "error: read: %s\n", strerror(errno));
celt_decoder_destroy(state);
celt_mode_destroy(mode);
return 1;
}

if (!tmp)
{
break;
}

if (tmp != rem)
{
rem -= tmp;
continue;
}

if ((tmp = celt_decode(state, (void *)data, len, pcm, framesize)) < 0)
{
fprintf(stderr, "error: celt_decode: %s\n", celt_strerror(tmp));
celt_decoder_destroy(state);
celt_mode_destroy(mode);
return 1;
}
len = 0;

if (write(STDOUT_FILENO, pcm, sizeof(*pcm) * framesize * channels) < 0)
{
fprintf(stderr, "error: write: %s\n", strerror(errno));
celt_decoder_destroy(state);
celt_mode_destroy(mode);
return 1;
}
}
celt_decoder_destroy(state);
celt_mode_destroy(mode);
return 0;
}