xref: /aosp_15_r20/external/libopus/doc/trivial_example.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
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