title: How to encode and decode audio using opus
body: <p>I am trying integrate <strong>opus</strong> into my application, the encode and decode function returns positive value which means successfully, but the output audio can't play. Raw audio data can play as well. 
  Here is how I encode data. I use 4 bytes prefix to separate from each packet.</p>
  
  <pre><code>self.encoder = opus_encoder_create(24000, 1, OPUS_APPLICATION_VOIP, &amp;opusError);
  opus_encoder_ctl(self.encoder, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
  
  
  
  - (void) encodeBufferList:(AudioBufferList *)bufferList {
      BOOL success = TPCircularBufferProduceBytes(_circularBuffer, bufferList-&gt;mBuffers[0].mData, bufferList-&gt;mBuffers[0].mDataByteSize);
      if (!success) {
          NSLog(@"insufficient space in circular buffer!");
      }
  
      if (!_encoding) {
              _encoding = YES;
  
              dispatch_async(self.processingQueue, ^{
                  [self startEncodingLoop];
              });
      }
  }
  
  
  -(void)startEncodingLoop
  {
      int32_t availableBytes = 0;
      opus_int16 *data = (opus_int16*)TPCircularBufferTail(_circularBuffer, &amp;availableBytes);
      int availableSamples = availableBytes / _inputASBD.mBytesPerFrame;
  
      /*!
       *  Use dynamic duration
       */
  //    int validSamples[6] = {2.5, 5, 10, 20, 40, 60}; // in milisecond
  //    int esample = validSamples[0] * self.sampleRate / 1000;
  //    for (int i = 0; i &lt; 6; i++) {
  //        int32_t samp = validSamples[i] * self.sampleRate / 1000;
  //        if (availableSamples &lt; samp) {
  //            break;
  //        }
  //        esample = samp;
  //    }
  
      /*!
       *  Use 20ms
       */
      int esample = 20 * self.sampleRate / 1000;
  
      if (availableSamples &lt; esample) {
          /*!
           *  Out of data. Finish encoding
           */
          self.encoding = NO;
          [self.eDelegate didFinishEncode];
          return;
      }
  
  //    printf("raw input value for packet \n");
  //    for (int i = 0; i &lt; esample * self.numberOfChannels; i++) {
  //        printf("%d :", data[i]);
  //    }
  
      int returnValue = opus_encode(_encoder, data, esample, _encoderOutputBuffer, 1000);
  
      TPCircularBufferConsume(_circularBuffer, esample * sizeof(opus_int16) * self.numberOfChannels);
  
  //    printf("output encode \n");
  //    for (int i = 0; i &lt; returnValue; i++) {
  //        printf("%d :", _encoderOutputBuffer[i]);
  //    }
  
      NSMutableData *outputData = [NSMutableData new];
      NSError *error = nil;
      if (returnValue &lt;= 0) {
          error = [OKUtilities errorForOpusErrorCode:returnValue];
      }else {
          [outputData appendBytes:_encoderOutputBuffer length:returnValue * sizeof(unsigned char)];
          unsigned char int_field[4];
          int_to_char(returnValue , int_field);
          NSData *header = [NSData dataWithBytes:&amp;int_field[0] length:4 * sizeof(unsigned char)];
          if (self.eDelegate) {
              [self.eDelegate didEncodeWithData:header];
          }
      }
  
      if (self.eDelegate) {
          [self.eDelegate didEncodeWithData:outputData];
      }
  
      [self startEncodingLoop];
  }
  </code></pre>
  
  <p>And here is decode function: </p>
  
  <pre><code>self.decoder = opus_decoder_create(24000, 1, &amp;opusError);
  opus_decoder_ctl(self.decoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
  opus_decoder_ctl(self.decoder, OPUS_SET_GAIN(10));
  
  
  -(void)startParseData:(unsigned char*)data remainingLen:(int)len
  {
      if (len &lt;= 0) {
          [self.dDelegate didFinishDecode];
          return;
      }
      int headLen = sizeof(unsigned char) * 4;
      unsigned char h[4];
      h[0] = data[0];
      h[1] = data[1];
      h[2] = data[2];
      h[3] = data[3];
  
      int packetLen = char_to_int(h);
      data += headLen;
      packetLen = packetLen * sizeof(unsigned char) * self.numberOfChannels;
      [self decodePacket:data length:packetLen remainingLen:len - headLen];
  }
  
  -(void)decodePacket:(unsigned char*)inputData length:(int)len remainingLen:(int)rl
  {
      int bw = opus_packet_get_bandwidth(inputData); //TEST: return OPUS_BANDWIDTH_SUPERWIDEBAND here
      int32_t decodedSamples = 0;
  
  //    int validSamples[6] = {2.5, 5, 10, 20, 40, 60}; // in milisecond
      /*!
       *  Use 60ms
       */
      int esample = 60 * self.sampleRate / 1000;
  //    printf("input decode \n");
  //    for (int i = 0; i &lt; len; i++) {
  //        printf("%d :", inputData[i]);
  //    }
  
      _decoderBufferLength = esample * self.numberOfChannels * sizeof(opus_int16);
      int returnValue = opus_decode(_decoder, inputData, len, _outputBuffer, esample, 1);
      if (returnValue &lt; 0) {
          NSError *error = [OKUtilities errorForOpusErrorCode:returnValue];
          NSLog(@"decode error %@", error);
          inputData += len;
          [self startParseData:inputData remainingLen:rl - len];
          return;
      }
      decodedSamples = returnValue;
  
      NSUInteger length = decodedSamples * self.numberOfChannels;
  
  //    printf("raw decoded data \n");
  //    for (int i = 0; i &lt; length; i++) {
  //        printf("%d :", _outputBuffer[i]);
  //    }
  
      NSData *audioData = [NSData dataWithBytes:_outputBuffer length:length * sizeof(opus_int16)];
      if (self.dDelegate) {
          [self.dDelegate didDecodeData:audioData];
      }
      inputData += len;
      [self startParseData:inputData remainingLen:rl - len];
  }
  </code></pre>
  
  <p>Please help me to point out what I am missing. An example would be great. </p>