1*a58d3d2aSXin Li /* Copyright (c) 2013 Jean-Marc Valin */
2*a58d3d2aSXin Li /*
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li
7*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright
8*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer.
9*a58d3d2aSXin Li
10*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
11*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
12*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
13*a58d3d2aSXin Li
14*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*a58d3d2aSXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*a58d3d2aSXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17*a58d3d2aSXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
18*a58d3d2aSXin Li OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*a58d3d2aSXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*a58d3d2aSXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21*a58d3d2aSXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22*a58d3d2aSXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23*a58d3d2aSXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*a58d3d2aSXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a58d3d2aSXin Li */
26*a58d3d2aSXin Li
27*a58d3d2aSXin Li /* This is meant to be a simple example of encoding and decoding audio
28*a58d3d2aSXin Li using Opus. It should make it easy to understand how the Opus API
29*a58d3d2aSXin Li works. For more information, see the full API documentation at:
30*a58d3d2aSXin Li https://www.opus-codec.org/docs/ */
31*a58d3d2aSXin Li
32*a58d3d2aSXin Li #include <stdlib.h>
33*a58d3d2aSXin Li #include <errno.h>
34*a58d3d2aSXin Li #include <string.h>
35*a58d3d2aSXin Li #include <opus.h>
36*a58d3d2aSXin Li #include <stdio.h>
37*a58d3d2aSXin Li
38*a58d3d2aSXin Li /*The frame size is hardcoded for this sample code but it doesn't have to be*/
39*a58d3d2aSXin Li #define FRAME_SIZE 960
40*a58d3d2aSXin Li #define SAMPLE_RATE 48000
41*a58d3d2aSXin Li #define CHANNELS 2
42*a58d3d2aSXin Li #define APPLICATION OPUS_APPLICATION_AUDIO
43*a58d3d2aSXin Li #define BITRATE 64000
44*a58d3d2aSXin Li
45*a58d3d2aSXin Li #define MAX_FRAME_SIZE 6*960
46*a58d3d2aSXin Li #define MAX_PACKET_SIZE (3*1276)
47*a58d3d2aSXin Li
main(int argc,char ** argv)48*a58d3d2aSXin Li int main(int argc, char **argv)
49*a58d3d2aSXin Li {
50*a58d3d2aSXin Li char *inFile;
51*a58d3d2aSXin Li FILE *fin;
52*a58d3d2aSXin Li char *outFile;
53*a58d3d2aSXin Li FILE *fout;
54*a58d3d2aSXin Li opus_int16 in[FRAME_SIZE*CHANNELS];
55*a58d3d2aSXin Li opus_int16 out[MAX_FRAME_SIZE*CHANNELS];
56*a58d3d2aSXin Li unsigned char cbits[MAX_PACKET_SIZE];
57*a58d3d2aSXin Li int nbBytes;
58*a58d3d2aSXin Li /*Holds the state of the encoder and decoder */
59*a58d3d2aSXin Li OpusEncoder *encoder;
60*a58d3d2aSXin Li OpusDecoder *decoder;
61*a58d3d2aSXin Li int err;
62*a58d3d2aSXin Li
63*a58d3d2aSXin Li if (argc != 3)
64*a58d3d2aSXin Li {
65*a58d3d2aSXin Li fprintf(stderr, "usage: trivial_example input.pcm output.pcm\n");
66*a58d3d2aSXin Li fprintf(stderr, "input and output are 16-bit little-endian raw files\n");
67*a58d3d2aSXin Li return EXIT_FAILURE;
68*a58d3d2aSXin Li }
69*a58d3d2aSXin Li
70*a58d3d2aSXin Li /*Create a new encoder state */
71*a58d3d2aSXin Li encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &err);
72*a58d3d2aSXin Li if (err<0)
73*a58d3d2aSXin Li {
74*a58d3d2aSXin Li fprintf(stderr, "failed to create an encoder: %s\n", opus_strerror(err));
75*a58d3d2aSXin Li return EXIT_FAILURE;
76*a58d3d2aSXin Li }
77*a58d3d2aSXin Li /* Set the desired bit-rate. You can also set other parameters if needed.
78*a58d3d2aSXin Li The Opus library is designed to have good defaults, so only set
79*a58d3d2aSXin Li parameters you know you need. Doing otherwise is likely to result
80*a58d3d2aSXin Li in worse quality, but better. */
81*a58d3d2aSXin Li err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE));
82*a58d3d2aSXin Li if (err<0)
83*a58d3d2aSXin Li {
84*a58d3d2aSXin Li fprintf(stderr, "failed to set bitrate: %s\n", opus_strerror(err));
85*a58d3d2aSXin Li return EXIT_FAILURE;
86*a58d3d2aSXin Li }
87*a58d3d2aSXin Li inFile = argv[1];
88*a58d3d2aSXin Li fin = fopen(inFile, "rb");
89*a58d3d2aSXin Li if (fin==NULL)
90*a58d3d2aSXin Li {
91*a58d3d2aSXin Li fprintf(stderr, "failed to open input file: %s\n", strerror(errno));
92*a58d3d2aSXin Li return EXIT_FAILURE;
93*a58d3d2aSXin Li }
94*a58d3d2aSXin Li
95*a58d3d2aSXin Li
96*a58d3d2aSXin Li /* Create a new decoder state. */
97*a58d3d2aSXin Li decoder = opus_decoder_create(SAMPLE_RATE, CHANNELS, &err);
98*a58d3d2aSXin Li if (err<0)
99*a58d3d2aSXin Li {
100*a58d3d2aSXin Li fprintf(stderr, "failed to create decoder: %s\n", opus_strerror(err));
101*a58d3d2aSXin Li return EXIT_FAILURE;
102*a58d3d2aSXin Li }
103*a58d3d2aSXin Li outFile = argv[2];
104*a58d3d2aSXin Li fout = fopen(outFile, "wb");
105*a58d3d2aSXin Li if (fout==NULL)
106*a58d3d2aSXin Li {
107*a58d3d2aSXin Li fprintf(stderr, "failed to open output file: %s\n", strerror(errno));
108*a58d3d2aSXin Li return EXIT_FAILURE;
109*a58d3d2aSXin Li }
110*a58d3d2aSXin Li
111*a58d3d2aSXin Li while (1)
112*a58d3d2aSXin Li {
113*a58d3d2aSXin Li int i;
114*a58d3d2aSXin Li unsigned char pcm_bytes[MAX_FRAME_SIZE*CHANNELS*2];
115*a58d3d2aSXin Li int frame_size;
116*a58d3d2aSXin Li size_t samples;
117*a58d3d2aSXin Li
118*a58d3d2aSXin Li /* Read a 16 bits/sample audio frame. */
119*a58d3d2aSXin Li samples = fread(pcm_bytes, sizeof(short)*CHANNELS, FRAME_SIZE, fin);
120*a58d3d2aSXin Li
121*a58d3d2aSXin Li /* For simplicity, only read whole frames. In a real application,
122*a58d3d2aSXin Li * we'd pad the final partial frame with zeroes, record the exact
123*a58d3d2aSXin Li * duration, and trim the decoded audio to match.
124*a58d3d2aSXin Li */
125*a58d3d2aSXin Li if (samples != FRAME_SIZE)
126*a58d3d2aSXin Li {
127*a58d3d2aSXin Li break;
128*a58d3d2aSXin Li }
129*a58d3d2aSXin Li
130*a58d3d2aSXin Li /* Convert from little-endian ordering. */
131*a58d3d2aSXin Li for (i=0;i<CHANNELS*FRAME_SIZE;i++)
132*a58d3d2aSXin Li {
133*a58d3d2aSXin Li in[i]=pcm_bytes[2*i+1]<<8|pcm_bytes[2*i];
134*a58d3d2aSXin Li }
135*a58d3d2aSXin Li
136*a58d3d2aSXin Li /* Encode the frame. */
137*a58d3d2aSXin Li nbBytes = opus_encode(encoder, in, FRAME_SIZE, cbits, MAX_PACKET_SIZE);
138*a58d3d2aSXin Li if (nbBytes<0)
139*a58d3d2aSXin Li {
140*a58d3d2aSXin Li fprintf(stderr, "encode failed: %s\n", opus_strerror(nbBytes));
141*a58d3d2aSXin Li return EXIT_FAILURE;
142*a58d3d2aSXin Li }
143*a58d3d2aSXin Li
144*a58d3d2aSXin Li
145*a58d3d2aSXin Li /* Decode the data. In this example, frame_size will be constant because
146*a58d3d2aSXin Li the encoder is using a constant frame size. However, that may not
147*a58d3d2aSXin Li be the case for all encoders, so the decoder must always check
148*a58d3d2aSXin Li the frame size returned. */
149*a58d3d2aSXin Li frame_size = opus_decode(decoder, cbits, nbBytes, out, MAX_FRAME_SIZE, 0);
150*a58d3d2aSXin Li if (frame_size<0)
151*a58d3d2aSXin Li {
152*a58d3d2aSXin Li fprintf(stderr, "decoder failed: %s\n", opus_strerror(frame_size));
153*a58d3d2aSXin Li return EXIT_FAILURE;
154*a58d3d2aSXin Li }
155*a58d3d2aSXin Li
156*a58d3d2aSXin Li /* Convert to little-endian ordering. */
157*a58d3d2aSXin Li for(i=0;i<CHANNELS*frame_size;i++)
158*a58d3d2aSXin Li {
159*a58d3d2aSXin Li pcm_bytes[2*i]=out[i]&0xFF;
160*a58d3d2aSXin Li pcm_bytes[2*i+1]=(out[i]>>8)&0xFF;
161*a58d3d2aSXin Li }
162*a58d3d2aSXin Li /* Write the decoded audio to file. */
163*a58d3d2aSXin Li fwrite(pcm_bytes, sizeof(short), frame_size*CHANNELS, fout);
164*a58d3d2aSXin Li }
165*a58d3d2aSXin Li /*Destroy the encoder state*/
166*a58d3d2aSXin Li opus_encoder_destroy(encoder);
167*a58d3d2aSXin Li opus_decoder_destroy(decoder);
168*a58d3d2aSXin Li fclose(fin);
169*a58d3d2aSXin Li fclose(fout);
170*a58d3d2aSXin Li return EXIT_SUCCESS;
171*a58d3d2aSXin Li }
172