|
Packit |
664db3 |
/* Copyright (C) 2002-2008 Jean-Marc Valin
|
|
Packit |
664db3 |
File: celtenc.c
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
664db3 |
modification, are permitted provided that the following conditions
|
|
Packit |
664db3 |
are met:
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions of source code must retain the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Redistributions in binary form must reproduce the above copyright
|
|
Packit |
664db3 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
664db3 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
- Neither the name of the Xiph.org Foundation nor the names of its
|
|
Packit |
664db3 |
contributors may be used to endorse or promote products derived from
|
|
Packit |
664db3 |
this software without specific prior written permission.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
664db3 |
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
664db3 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
664db3 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
|
Packit |
664db3 |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
Packit |
664db3 |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
Packit |
664db3 |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
Packit |
664db3 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
Packit |
664db3 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
Packit |
664db3 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
Packit |
664db3 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
664db3 |
# include "config.h"
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include <stdio.h>
|
|
Packit |
664db3 |
#if !defined WIN32 && !defined _WIN32
|
|
Packit |
664db3 |
#include <unistd.h>
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifdef HAVE_GETOPT_H
|
|
Packit |
664db3 |
#include <getopt.h>
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#ifndef HAVE_GETOPT_LONG
|
|
Packit |
664db3 |
#include "getopt_win.h"
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include <stdlib.h>
|
|
Packit |
664db3 |
#include <string.h>
|
|
Packit |
664db3 |
#include <time.h>
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include "celt.h"
|
|
Packit |
664db3 |
#include "celt_header.h"
|
|
Packit |
664db3 |
#include <ogg/ogg.h>
|
|
Packit |
664db3 |
#include "wav_io.h"
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#if defined WIN32 || defined _WIN32
|
|
Packit |
664db3 |
/* We need the following two to set stdout to binary */
|
|
Packit |
664db3 |
#include <io.h>
|
|
Packit |
664db3 |
#include <fcntl.h>
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#include "skeleton.h"
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void comment_init(char **comments, int* length, char *vendor_string);
|
|
Packit |
664db3 |
void comment_add(char **comments, int* length, char *tag, char *val);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Write an Ogg page to a file pointer*/
|
|
Packit |
664db3 |
int oe_write_page(ogg_page *page, FILE *fp)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int written;
|
|
Packit |
664db3 |
written = fwrite(page->header,1,page->header_len, fp);
|
|
Packit |
664db3 |
written += fwrite(page->body,1,page->body_len, fp);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
return written;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#define MAX_FRAME_SIZE 2000
|
|
Packit |
664db3 |
#define MAX_FRAME_BYTES 2000
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* Convert input audio bits, endians and channels */
|
|
Packit |
664db3 |
static int read_samples(FILE *fin,int frame_size, int bits, int channels, int lsb, short * input, char *buff, celt_int32_t *size)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
unsigned char in[MAX_FRAME_BYTES*2];
|
|
Packit |
664db3 |
int i;
|
|
Packit |
664db3 |
short *s;
|
|
Packit |
664db3 |
int nb_read;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (size && *size<=0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
return 0;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
/*Read input audio*/
|
|
Packit |
664db3 |
if (size)
|
|
Packit |
664db3 |
*size -= bits/8*channels*frame_size;
|
|
Packit |
664db3 |
if (buff)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
for (i=0;i<12;i++)
|
|
Packit |
664db3 |
in[i]=buff[i];
|
|
Packit |
664db3 |
nb_read = fread(in+12,1,bits/8*channels*frame_size-12, fin) + 12;
|
|
Packit |
664db3 |
if (size)
|
|
Packit |
664db3 |
*size += 12;
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
nb_read = fread(in,1,bits/8*channels* frame_size, fin);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
nb_read /= bits/8*channels;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*fprintf (stderr, "%d\n", nb_read);*/
|
|
Packit |
664db3 |
if (nb_read==0)
|
|
Packit |
664db3 |
return 0;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
s=(short*)in;
|
|
Packit |
664db3 |
if(bits==8)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
/* Convert 8->16 bits */
|
|
Packit |
664db3 |
for(i=frame_size*channels-1;i>=0;i--)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
s[i]=(in[i]<<8)^0x8000;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
} else
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
/* convert to our endian format */
|
|
Packit |
664db3 |
for(i=0;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if(lsb)
|
|
Packit |
664db3 |
s[i]=le_short(s[i]);
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
s[i]=be_short(s[i]);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* FIXME: This is probably redundent now */
|
|
Packit |
664db3 |
/* copy to float input buffer */
|
|
Packit |
664db3 |
for (i=0;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
input[i]=(short)s[i];
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
for (i=nb_read*channels;i
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
input[i]=0;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
return nb_read;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void add_fishead_packet (ogg_stream_state *os) {
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
fishead_packet fp;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
memset(&fp, 0, sizeof(fp));
|
|
Packit |
664db3 |
fp.ptime_n = 0;
|
|
Packit |
664db3 |
fp.ptime_d = 1000;
|
|
Packit |
664db3 |
fp.btime_n = 0;
|
|
Packit |
664db3 |
fp.btime_d = 1000;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
add_fishead_to_stream(os, &fp);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*
|
|
Packit |
664db3 |
* Adds the fishead packets in the skeleton output stream along with the e_o_s packet
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
void add_fisbone_packet (ogg_stream_state *os, celt_int32_t serialno, CELT051Header *header) {
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
fisbone_packet fp;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
memset(&fp, 0, sizeof(fp));
|
|
Packit |
664db3 |
fp.serial_no = serialno;
|
|
Packit |
664db3 |
fp.nr_header_packet = 2 + header->extra_headers;
|
|
Packit |
664db3 |
fp.granule_rate_n = header->sample_rate;
|
|
Packit |
664db3 |
fp.granule_rate_d = 1;
|
|
Packit |
664db3 |
fp.start_granule = 0;
|
|
Packit |
664db3 |
fp.preroll = 3;
|
|
Packit |
664db3 |
fp.granule_shift = 0;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
add_message_header_field(&fp, "Content-Type", "audio/x-celt");
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
add_fisbone_to_stream(os, &fp);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void version(void)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
printf ("celtenc (CELT encoder)\n");
|
|
Packit |
664db3 |
printf ("Copyright (C) 2008 Jean-Marc Valin\n");
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void version_short(void)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
printf ("celtenc (CELT encoder)\n");
|
|
Packit |
664db3 |
printf ("Copyright (C) 2008 Jean-Marc Valin\n");
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void usage(void)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
printf ("Usage: celtenc [options] input_file output_file.oga\n");
|
|
Packit |
664db3 |
printf ("\n");
|
|
Packit |
664db3 |
printf ("Encodes input_file using CELT. It can read the WAV or raw files.\n");
|
|
Packit |
664db3 |
printf ("\n");
|
|
Packit |
664db3 |
printf ("input_file can be:\n");
|
|
Packit |
664db3 |
printf (" filename.wav wav file\n");
|
|
Packit |
664db3 |
printf (" filename.* Raw PCM file (any extension other than .wav)\n");
|
|
Packit |
664db3 |
printf (" - stdin\n");
|
|
Packit |
664db3 |
printf ("\n");
|
|
Packit |
664db3 |
printf ("output_file can be:\n");
|
|
Packit |
664db3 |
printf (" filename.oga compressed file\n");
|
|
Packit |
664db3 |
printf (" - stdout\n");
|
|
Packit |
664db3 |
printf ("\n");
|
|
Packit |
664db3 |
printf ("Options:\n");
|
|
Packit |
664db3 |
printf (" --bitrate n Encoding bit-rate\n");
|
|
Packit |
664db3 |
printf (" --comp n Encoding complexity (0-10)\n");
|
|
Packit |
664db3 |
printf (" --skeleton Outputs ogg skeleton metadata (may cause incompatibilities)\n");
|
|
Packit |
664db3 |
printf (" --comment Add the given string as an extra comment. This may be\n");
|
|
Packit |
664db3 |
printf (" used multiple times\n");
|
|
Packit |
664db3 |
printf (" --author Author of this track\n");
|
|
Packit |
664db3 |
printf (" --title Title for this track\n");
|
|
Packit |
664db3 |
printf (" -h, --help This help\n");
|
|
Packit |
664db3 |
printf (" -v, --version Version information\n");
|
|
Packit |
664db3 |
printf (" -V Verbose mode (show bit-rate)\n");
|
|
Packit |
664db3 |
printf ("Raw input options:\n");
|
|
Packit |
664db3 |
printf (" --rate n Sampling rate for raw input\n");
|
|
Packit |
664db3 |
printf (" --mono Consider raw input as mono\n");
|
|
Packit |
664db3 |
printf (" --stereo Consider raw input as stereo\n");
|
|
Packit |
664db3 |
printf (" --le Raw input is little-endian\n");
|
|
Packit |
664db3 |
printf (" --be Raw input is big-endian\n");
|
|
Packit |
664db3 |
printf (" --8bit Raw input is 8-bit unsigned\n");
|
|
Packit |
664db3 |
printf (" --16bit Raw input is 16-bit signed\n");
|
|
Packit |
664db3 |
printf ("Default raw PCM input is 16-bit, little-endian, mono\n");
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
int main(int argc, char **argv)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int nb_samples, total_samples=0, nb_encoded;
|
|
Packit |
664db3 |
int c;
|
|
Packit |
664db3 |
int option_index = 0;
|
|
Packit |
664db3 |
char *inFile, *outFile;
|
|
Packit |
664db3 |
FILE *fin, *fout;
|
|
Packit |
664db3 |
short input[MAX_FRAME_SIZE];
|
|
Packit |
664db3 |
celt_int32_t frame_size;
|
|
Packit |
664db3 |
int quiet=0;
|
|
Packit |
664db3 |
int nbBytes;
|
|
Packit |
664db3 |
CELTMode *mode;
|
|
Packit |
664db3 |
void *st;
|
|
Packit |
664db3 |
unsigned char bits[MAX_FRAME_BYTES];
|
|
Packit |
664db3 |
int with_skeleton = 0;
|
|
Packit |
664db3 |
struct option long_options[] =
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
{"bitrate", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{"comp", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{"skeleton",no_argument,NULL, 0},
|
|
Packit |
664db3 |
{"help", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"quiet", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"le", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"be", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"8bit", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"16bit", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"mono", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"stereo", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"rate", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{"version", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"version-short", no_argument, NULL, 0},
|
|
Packit |
664db3 |
{"comment", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{"author", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{"title", required_argument, NULL, 0},
|
|
Packit |
664db3 |
{0, 0, 0, 0}
|
|
Packit |
664db3 |
};
|
|
Packit |
664db3 |
int print_bitrate=0;
|
|
Packit |
664db3 |
celt_int32_t rate=44100;
|
|
Packit |
664db3 |
celt_int32_t size;
|
|
Packit |
664db3 |
int chan=1;
|
|
Packit |
664db3 |
int fmt=16;
|
|
Packit |
664db3 |
int lsb=1;
|
|
Packit |
664db3 |
ogg_stream_state os;
|
|
Packit |
664db3 |
ogg_stream_state so; /* ogg stream for skeleton bitstream */
|
|
Packit |
664db3 |
ogg_page og;
|
|
Packit |
664db3 |
ogg_packet op;
|
|
Packit |
664db3 |
int bytes_written=0, ret, result;
|
|
Packit |
664db3 |
int id=-1;
|
|
Packit |
664db3 |
CELT051Header header;
|
|
Packit |
664db3 |
char vendor_string[64];
|
|
Packit |
664db3 |
char *comments;
|
|
Packit |
664db3 |
int comments_length;
|
|
Packit |
664db3 |
int close_in=0, close_out=0;
|
|
Packit |
664db3 |
int eos=0;
|
|
Packit |
664db3 |
celt_int32_t bitrate=-1;
|
|
Packit |
664db3 |
char first_bytes[12];
|
|
Packit |
664db3 |
int wave_input=0;
|
|
Packit |
664db3 |
celt_int32_t lookahead = 0;
|
|
Packit |
664db3 |
int bytes_per_packet=48;
|
|
Packit |
664db3 |
int complexity=-127;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
snprintf(vendor_string, sizeof(vendor_string), "Encoded with CELT\n");
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
comment_init(&comments, &comments_length, vendor_string);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Process command-line options*/
|
|
Packit |
664db3 |
while(1)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
c = getopt_long (argc, argv, "hvV",
|
|
Packit |
664db3 |
long_options, &option_index);
|
|
Packit |
664db3 |
if (c==-1)
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
switch(c)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
case 0:
|
|
Packit |
664db3 |
if (strcmp(long_options[option_index].name,"bitrate")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
bitrate = atoi (optarg);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"skeleton")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
with_skeleton=1;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"help")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
usage();
|
|
Packit |
664db3 |
exit(0);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"quiet")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
quiet = 1;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"version")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
version();
|
|
Packit |
664db3 |
exit(0);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"version-short")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
version_short();
|
|
Packit |
664db3 |
exit(0);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"le")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
lsb=1;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"be")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
lsb=0;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"8bit")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fmt=8;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"16bit")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fmt=16;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"stereo")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
chan=2;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"mono")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
chan=1;
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"rate")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
rate=atoi (optarg);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"comp")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
complexity=atoi (optarg);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"comment")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if (!strchr(optarg, '='))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr, "Invalid comment: %s\n", optarg);
|
|
Packit |
664db3 |
fprintf (stderr, "Comments must be of the form name=value\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
comment_add(&comments, &comments_length, NULL, optarg);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"author")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
comment_add(&comments, &comments_length, "author=", optarg);
|
|
Packit |
664db3 |
} else if (strcmp(long_options[option_index].name,"title")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
comment_add(&comments, &comments_length, "title=", optarg);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
case 'h':
|
|
Packit |
664db3 |
usage();
|
|
Packit |
664db3 |
exit(0);
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
case 'v':
|
|
Packit |
664db3 |
version();
|
|
Packit |
664db3 |
exit(0);
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
case 'V':
|
|
Packit |
664db3 |
print_bitrate=1;
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
case '?':
|
|
Packit |
664db3 |
usage();
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
fprintf(stderr,"\nWARNING: This encoder is a CELT *PRERELEASE*. It produces streams that are\n"
|
|
Packit |
664db3 |
" not decodable by ANY OTHER VERSION. These streams will NOT be\n"
|
|
Packit |
664db3 |
" supported or decodable by any future CELT release.\n\n");
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (argc-optind!=2)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
usage();
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
inFile=argv[optind];
|
|
Packit |
664db3 |
outFile=argv[optind+1];
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Initialize Ogg stream struct*/
|
|
Packit |
664db3 |
srand(time(NULL));
|
|
Packit |
664db3 |
if (ogg_stream_init(&os, rand())==-1)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf(stderr,"Error: stream init failed\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (with_skeleton && ogg_stream_init(&so, rand())==-1)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf(stderr,"Error: stream init failed\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (strcmp(inFile, "-")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
#if defined WIN32 || defined _WIN32
|
|
Packit |
664db3 |
_setmode(_fileno(stdin), _O_BINARY);
|
|
Packit |
664db3 |
#elif defined OS2
|
|
Packit |
664db3 |
_fsetmode(stdin,"b");
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
fin=stdin;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fin = fopen(inFile, "rb");
|
|
Packit |
664db3 |
if (!fin)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
perror(inFile);
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
close_in=1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fread(first_bytes, 1, 12, fin);
|
|
Packit |
664db3 |
if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1)
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
wave_input=1;
|
|
Packit |
664db3 |
lsb=1; /* CHECK: exists big-endian .wav ?? */
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (chan == 1)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if (bitrate < 0)
|
|
Packit |
664db3 |
bitrate = 64;
|
|
Packit |
664db3 |
if (bitrate < 32)
|
|
Packit |
664db3 |
bitrate = 32;
|
|
Packit |
664db3 |
if (bitrate > 110)
|
|
Packit |
664db3 |
bitrate = 110;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else if (chan == 2)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if (bitrate < 0)
|
|
Packit |
664db3 |
bitrate = 128;
|
|
Packit |
664db3 |
if (bitrate < 64)
|
|
Packit |
664db3 |
bitrate = 64;
|
|
Packit |
664db3 |
if (bitrate > 150)
|
|
Packit |
664db3 |
bitrate = 150;
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
fprintf (stderr, "Only mono and stereo are supported\n");
|
|
Packit |
664db3 |
return 1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
mode = celt051_mode_create(rate, chan, 256, NULL);
|
|
Packit |
664db3 |
if (!mode)
|
|
Packit |
664db3 |
return 1;
|
|
Packit |
664db3 |
celt051_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
celt051_header_init(&header, mode);
|
|
Packit |
664db3 |
header.nb_channels = chan;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
char *st_string="mono";
|
|
Packit |
664db3 |
if (chan==2)
|
|
Packit |
664db3 |
st_string="stereo";
|
|
Packit |
664db3 |
if (!quiet)
|
|
Packit |
664db3 |
fprintf (stderr, "Encoding %d Hz audio using %s (%d bytes per packet)\n",
|
|
Packit |
664db3 |
header.sample_rate, st_string, bytes_per_packet);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
/*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n",
|
|
Packit |
664db3 |
header.rate, mode->bitrate, mode->modeName);*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Initialize CELT encoder*/
|
|
Packit |
664db3 |
st = celt051_encoder_create(mode);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (complexity!=-127) {
|
|
Packit |
664db3 |
if (celt051_encoder_ctl(st, CELT_SET_COMPLEXITY(complexity)) != CELT_OK)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr, "Only complexity 0 through 10 is supported\n");
|
|
Packit |
664db3 |
return 1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (strcmp(outFile,"-")==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
#if defined WIN32 || defined _WIN32
|
|
Packit |
664db3 |
_setmode(_fileno(stdout), _O_BINARY);
|
|
Packit |
664db3 |
#endif
|
|
Packit |
664db3 |
fout=stdout;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fout = fopen(outFile, "wb");
|
|
Packit |
664db3 |
if (!fout)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
perror(outFile);
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
close_out=1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (with_skeleton) {
|
|
Packit |
664db3 |
fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n");
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* first packet should be the skeleton header. */
|
|
Packit |
664db3 |
if (with_skeleton) {
|
|
Packit |
664db3 |
add_fishead_packet(&so);
|
|
Packit |
664db3 |
if ((ret = flush_ogg_stream_to_file(&so, fout))) {
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
} else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Write header*/
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
unsigned char header_data[100];
|
|
Packit |
664db3 |
int packet_size = celt051_header_to_packet(&header, header_data, 100);
|
|
Packit |
664db3 |
op.packet = header_data;
|
|
Packit |
664db3 |
op.bytes = packet_size;
|
|
Packit |
664db3 |
op.b_o_s = 1;
|
|
Packit |
664db3 |
op.e_o_s = 0;
|
|
Packit |
664db3 |
op.granulepos = 0;
|
|
Packit |
664db3 |
op.packetno = 0;
|
|
Packit |
664db3 |
ogg_stream_packetin(&os, &op);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
while((result = ogg_stream_flush(&os, &og)))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if(!result) break;
|
|
Packit |
664db3 |
ret = oe_write_page(&og, fout);
|
|
Packit |
664db3 |
if(ret != og.header_len + og.body_len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
op.packet = (unsigned char *)comments;
|
|
Packit |
664db3 |
op.bytes = comments_length;
|
|
Packit |
664db3 |
op.b_o_s = 0;
|
|
Packit |
664db3 |
op.e_o_s = 0;
|
|
Packit |
664db3 |
op.granulepos = 0;
|
|
Packit |
664db3 |
op.packetno = 1;
|
|
Packit |
664db3 |
ogg_stream_packetin(&os, &op);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* fisbone packet should be write after all bos pages */
|
|
Packit |
664db3 |
if (with_skeleton) {
|
|
Packit |
664db3 |
add_fisbone_packet(&so, os.serialno, &header);
|
|
Packit |
664db3 |
if ((ret = flush_ogg_stream_to_file(&so, fout))) {
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
} else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* writing the rest of the celt header packets */
|
|
Packit |
664db3 |
while((result = ogg_stream_flush(&os, &og)))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
if(!result) break;
|
|
Packit |
664db3 |
ret = oe_write_page(&og, fout);
|
|
Packit |
664db3 |
if(ret != og.header_len + og.body_len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
free(comments);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/* write the skeleton eos packet */
|
|
Packit |
664db3 |
if (with_skeleton) {
|
|
Packit |
664db3 |
add_eos_packet_to_stream(&so);
|
|
Packit |
664db3 |
if ((ret = flush_ogg_stream_to_file(&so, fout))) {
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing skeleton header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
} else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (!wave_input)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL);
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (nb_samples==0)
|
|
Packit |
664db3 |
eos=1;
|
|
Packit |
664db3 |
total_samples += nb_samples;
|
|
Packit |
664db3 |
nb_encoded = -lookahead;
|
|
Packit |
664db3 |
/*Main encoding loop (one frame per iteration)*/
|
|
Packit |
664db3 |
while (!eos || total_samples>nb_encoded)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
id++;
|
|
Packit |
664db3 |
/*Encode current frame*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
nbBytes = celt051_encode(st, input, NULL, bits, bytes_per_packet);
|
|
Packit |
664db3 |
if (nbBytes<0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf(stderr, "Got error %d while encoding. Aborting.\n", nbBytes);
|
|
Packit |
664db3 |
break;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
nb_encoded += frame_size;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (wave_input)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
|
|
Packit |
664db3 |
} else {
|
|
Packit |
664db3 |
nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (nb_samples==0)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
eos=1;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
if (eos && total_samples<=nb_encoded)
|
|
Packit |
664db3 |
op.e_o_s = 1;
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
op.e_o_s = 0;
|
|
Packit |
664db3 |
total_samples += nb_samples;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
op.packet = (unsigned char *)bits;
|
|
Packit |
664db3 |
op.bytes = nbBytes;
|
|
Packit |
664db3 |
op.b_o_s = 0;
|
|
Packit |
664db3 |
/*Is this redundent?*/
|
|
Packit |
664db3 |
if (eos && total_samples<=nb_encoded)
|
|
Packit |
664db3 |
op.e_o_s = 1;
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
op.e_o_s = 0;
|
|
Packit |
664db3 |
op.granulepos = (id+1)*frame_size-lookahead;
|
|
Packit |
664db3 |
if (op.granulepos>total_samples)
|
|
Packit |
664db3 |
op.granulepos = total_samples;
|
|
Packit |
664db3 |
/*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/
|
|
Packit |
664db3 |
op.packetno = 2+id;
|
|
Packit |
664db3 |
ogg_stream_packetin(&os, &op);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*Write all new pages (most likely 0 or 1)*/
|
|
Packit |
664db3 |
while (ogg_stream_pageout(&os,&og))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
ret = oe_write_page(&og, fout);
|
|
Packit |
664db3 |
if(ret != og.header_len + og.body_len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
/*Flush all pages left to be written*/
|
|
Packit |
664db3 |
while (ogg_stream_flush(&os, &og))
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
ret = oe_write_page(&og, fout);
|
|
Packit |
664db3 |
if(ret != og.header_len + og.body_len)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
fprintf (stderr,"Error: failed writing header to output stream\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
else
|
|
Packit |
664db3 |
bytes_written += ret;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
celt051_encoder_destroy(st);
|
|
Packit |
664db3 |
celt051_mode_destroy(mode);
|
|
Packit |
664db3 |
ogg_stream_clear(&os);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
if (close_in)
|
|
Packit |
664db3 |
fclose(fin);
|
|
Packit |
664db3 |
if (close_out)
|
|
Packit |
664db3 |
fclose(fout);
|
|
Packit |
664db3 |
return 0;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
/*
|
|
Packit |
664db3 |
Comments will be stored in the Vorbis style.
|
|
Packit |
664db3 |
It is describled in the "Structure" section of
|
|
Packit |
664db3 |
http://www.xiph.org/ogg/vorbis/doc/v-comment.html
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
The comment header is decoded as follows:
|
|
Packit |
664db3 |
1) [vendor_length] = read an unsigned integer of 32 bits
|
|
Packit |
664db3 |
2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
|
|
Packit |
664db3 |
3) [user_comment_list_length] = read an unsigned integer of 32 bits
|
|
Packit |
664db3 |
4) iterate [user_comment_list_length] times {
|
|
Packit |
664db3 |
5) [length] = read an unsigned integer of 32 bits
|
|
Packit |
664db3 |
6) this iteration's user comment = read a UTF-8 vector as [length] octets
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
7) [framing_bit] = read a single bit as boolean
|
|
Packit |
664db3 |
8) if ( [framing_bit] unset or end of packet ) then ERROR
|
|
Packit |
664db3 |
9) done.
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
If you have troubles, please write to ymnk@jcraft.com.
|
|
Packit |
664db3 |
*/
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
|
|
Packit |
664db3 |
((buf[base+2]<<16)&0xff0000)| \
|
|
Packit |
664db3 |
((buf[base+1]<<8)&0xff00)| \
|
|
Packit |
664db3 |
(buf[base]&0xff))
|
|
Packit |
664db3 |
#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
|
|
Packit |
664db3 |
buf[base+2]=((val)>>16)&0xff; \
|
|
Packit |
664db3 |
buf[base+1]=((val)>>8)&0xff; \
|
|
Packit |
664db3 |
buf[base]=(val)&0xff; \
|
|
Packit |
664db3 |
}while(0)
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
void comment_init(char **comments, int* length, char *vendor_string)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
int vendor_length=strlen(vendor_string);
|
|
Packit |
664db3 |
int user_comment_list_length=0;
|
|
Packit |
664db3 |
int len=4+vendor_length+4;
|
|
Packit |
664db3 |
char *p=(char*)malloc(len);
|
|
Packit |
664db3 |
if(p==NULL){
|
|
Packit |
664db3 |
fprintf (stderr, "malloc failed in comment_init()\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
writeint(p, 0, vendor_length);
|
|
Packit |
664db3 |
memcpy(p+4, vendor_string, vendor_length);
|
|
Packit |
664db3 |
writeint(p, 4+vendor_length, user_comment_list_length);
|
|
Packit |
664db3 |
*length=len;
|
|
Packit |
664db3 |
*comments=p;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
void comment_add(char **comments, int* length, char *tag, char *val)
|
|
Packit |
664db3 |
{
|
|
Packit |
664db3 |
char* p=*comments;
|
|
Packit |
664db3 |
int vendor_length=readint(p, 0);
|
|
Packit |
664db3 |
int user_comment_list_length=readint(p, 4+vendor_length);
|
|
Packit |
664db3 |
int tag_len=(tag?strlen(tag):0);
|
|
Packit |
664db3 |
int val_len=strlen(val);
|
|
Packit |
664db3 |
int len=(*length)+4+tag_len+val_len;
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
p=(char*)realloc(p, len);
|
|
Packit |
664db3 |
if(p==NULL){
|
|
Packit |
664db3 |
fprintf (stderr, "realloc failed in comment_add()\n");
|
|
Packit |
664db3 |
exit(1);
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
writeint(p, *length, tag_len+val_len); /* length of comment */
|
|
Packit |
664db3 |
if(tag) memcpy(p+*length+4, tag, tag_len); /* comment */
|
|
Packit |
664db3 |
memcpy(p+*length+4+tag_len, val, val_len); /* comment */
|
|
Packit |
664db3 |
writeint(p, 4+vendor_length, user_comment_list_length+1);
|
|
Packit |
664db3 |
|
|
Packit |
664db3 |
*comments=p;
|
|
Packit |
664db3 |
*length=len;
|
|
Packit |
664db3 |
}
|
|
Packit |
664db3 |
#undef readint
|
|
Packit |
664db3 |
#undef writeint
|