Audio encoded into AAC on iOS platform

Source: Internet
Author: User

Before the introduction of decoding AAC, once used Fadd, and mentioned, if you want to encode into AAC format, you can use FACC, FDK-AAC, etc., but the use of FDK-AAC and other encoding methods, are soft coding, CPU consumption will be significantly larger than the hardware code.

The hard-coded advantage is the ability to perform coding tasks at high speed and low power with the integration of hardware chips.

On the iOS platform, it also provides the ability to hard-code, and app development only needs to invoke the appropriate SDK interface.

This SDK interface is audioconverter.

This article describes how to call Audioconverter on the iOS platform to complete the hard-coded AAC.

From the name point of view, Audioconverter is a format converter, where the small way to use it, the PCM format data, converted to AAC format data.

For media formats (encoded format or package format), readers can follow the "Guangzhou Xiao Cheng" public number and check the relevant articles in the "audio and video-based concepts and processes" menu.

Audioconverter the conversion in memory, do not need to write the file, and the Extaudiofile interface is the operation of the file, and the internal use of Audioconerter to convert the format, that is, the reader in a certain scenario, You can also use the Extaudiofile interface.

How to use Audioconverter? Basically, the call to the interface needs to read the corresponding header file and understand how to invoke it by looking at the document comments.

Demo here, how to convert PCM format data into AAC format data.

After the presentation of the code, the path is simply explained, and the reader needs to read the code patiently to understand it and apply it to its own development scenario.

The following example shows the implementation of a switch from PCM to AAC (such as the implementation of saving recording data to AAC).

typedef struct{void *source;    UInt32 sourcesize;    UInt32 Channelcount; Audiostreampacketdescription *packetdescriptions;} fillcomplexinputparam;//fill in the source data, i.e. PCM data osstatus Audioconvertercomplexinputdataproc (Audioconverterref inAudio                                            Converter, uint32* Ionumberdatapackets, audiobufferlist* Iodata, Audiostream                           packetdescription** Outdatapacketdescription, void*    Inuserdata) {fillcomplexinputparam* param = (fillcomplexinputparam*) inuserdata;        if (param->sourcesize <= 0) {*ionumberdatapackets = 0;    return-1;    } Iodata->mbuffers[0].mdata = param->source;    Iodata->mbuffers[0].mnumberchannels = param->channelcount;    Iodata->mbuffers[0].mdatabytesize = param->sourcesize; *ionumberdatapaCkets = 1;    param->sourcesize = 0;    Param->source = NULL; return NOERR;}    typedef struct _TAGCONVERTCONTEXT {AUDIOCONVERTERREF converter;    int samplerate; int channels;} convertcontext;//init//eventually creates convertcontext with Audioconverternewspecific, and sets properties such as bitrate void* convert_init (int sample_    rate, int channel_count) {audiostreambasicdescription sourcedes;    memset (&sourcedes, 0, sizeof (sourcedes));    Sourcedes.msamplerate = sample_rate;    Sourcedes.mformatid = KAUDIOFORMATLINEARPCM; Sourcedes.mformatflags = klinearpcmformatflagispacked |    Klinearpcmformatflagissignedinteger;    Sourcedes.mchannelsperframe = Channel_count;    Sourcedes.mbitsperchannel = 16;    Sourcedes.mbytesperframe = Sourcedes.mbitsperchannel/8*sourcedes.mchannelsperframe;    Sourcedes.mbytesperpacket = Sourcedes.mbytesperframe;    Sourcedes.mframesperpacket = 1;    sourcedes.mreserved = 0;    Audiostreambasicdescription Targetdes;    memset (&targetdes, 0, sizeof (targetdes)); Targetdes.mformAtid = KAUDIOFORMATMPEG4AAC;    Targetdes.msamplerate = sample_rate;    Targetdes.mchannelsperframe = Channel_count;    UInt32 size = sizeof (targetdes);    Audioformatgetproperty (kaudioformatproperty_formatinfo, 0, NULL, &size, &targetdes);    Audioclassdescription Audioclassdes;    memset (&audioclassdes, 0, sizeof (audioclassdescription)); Audioformatgetpropertyinfo (kaudioformatproperty_encoders, sizeof (Targetdes.mformatid), &targetdes.mformatid,    &size);    int encodercount = size/sizeof (audioclassdescription);    Audioclassdescription Descriptions[encodercount]; Audioformatgetproperty (kaudioformatproperty_encoders, sizeof (Targetdes.mformatid), &targetdes.mformatid,    &size, descriptions);  for (int pos = 0; pos < Encodercount; pos + +) {if (Targetdes.mformatid = = Descriptions[pos].msubtype && Descriptions[pos].mmanufacturer = = kapplesoftwareaudiocodecmanufacturer) {memcpy (&audioclassdes, &des Criptions[pos], sizeOf (audioclassdescription));        Break    }} Convertcontext *convertcontex = malloc (sizeof (Convertcontext)); osstatus ret = audioconverternewspecific (&sourcedes, &targetdes, 1, &audioclassdes, &convertContex-    >converter);        if (ret = = NOERR) {Audioconverterref converter = convertcontex->converter;        TMP = Kaudioconverterquality_high;        Audioconvertersetproperty (Converter, kaudioconvertercodecquality, sizeof (TMP), &tmp);        UInt32 bitrate = 96000;        UInt32 size = sizeof (bitrate);    ret = Audioconvertersetproperty (converter, kaudioconverterencodebitrate, size, &bitrate);        } else {free (Convertcontex);    Convertcontex = NULL; } return Convertcontex;} Convertingvoid convert (void* convertcontext, void* srcdata, int srclen, void** outdata, int* outlen) {Convertcontext    * Convertcxt = (convertcontext*) convertcontext; if (convertcxt && convertcxt->converter) {UInt32 theouputbufsize = Srclen;        UInt32 packetsize = 1;        void *outbuffer = malloc (theouputbufsize);        memset (outbuffer, 0, theouputbufsize);        Audiostreampacketdescription *outputpacketdescriptions = NULL; Outputpacketdescriptions = (audiostreampacketdescription*) malloc (sizeof (audiostreampacketdescription) * packetSize        );        Fillcomplexinputparam Userparam;        Userparam.source = Srcdata;        Userparam.sourcesize = Srclen;        Userparam.channelcount = convertcxt->channels;        Userparam.packetdescriptions = NULL;        osstatus ret = NOERR;        audiobufferlist* bufferlist = malloc (sizeof (audiobufferlist));        Audiobufferlist outputbuffers = *bufferlist;        Outputbuffers.mnumberbuffers = 1;        Outputbuffers.mbuffers[0].mnumberchannels = convertcxt->channels;        Outputbuffers.mbuffers[0].mdata = Outbuffer;        Outputbuffers.mbuffers[0].mdatabytesize = theouputbufsize; ret = Audioconverterfillcomplexbuffer (conveRtcxt->converter, Audioconvertercomplexinputdataproc, &userparam, &packetsize, &outputBuffers,        Outputpacketdescriptions); if (ret = = NOERR) {if (Outputbuffers.mbuffers[0].mdatabytesize > 0) {nsdata* RAWAAC = [NSDA                Ta datawithbytes:outputbuffers.mbuffers[0].mdata length:outputbuffers.mbuffers[0].mdatabytesize];                *outdata = malloc ([RAWAAC length]);                memcpy (*outdata, [rawaac bytes], [RAWAAC length]);                *outlen = (int) [RAWAAC length];//test converted AAC data, saved as ADTS-AAC file # if 1 int headerlength = 0; char* Packetheader = newadtsdataforpacketlength ((int) [RAWAAC length], convertcxt->samplerate, convertcxt->                channels, &headerlength);                nsdata* Adtspacketheader = [NSData datawithbytes:packetheader length:headerlength];                Free (packetheader);                nsmutabledata* fulldata = [Nsmutabledata Datawithdata:adtspacketheader]; [FulldaTa Appenddata:rawaac];                Nsfilemanager *filemgr = [Nsfilemanager Defaultmanager]; NSString *filepath = [Nshomedirectory () stringbyappendingformat:@ "/DOCUMENTS/TEST%P.AAC", ConvertCxt->converter]                ;                Nsfilehandle *file = nil; if (![                Filemgr Fileexistsatpath:filepath]) {[Filemgr createfileatpath:filepath contents:nil Attributes:nil];                } file = [Nsfilehandle Filehandleforwritingatpath:filepath];                [File Seektoendoffile];                [File Writedata:fulldata];        [File CloseFile]; #endif}} free (Outbuffer);        if (outputpacketdescriptions) {free (outputpacketdescriptions);     }}}//uninit//... int freqidxforadtsheader (int samplerate) {/** 0:96000 hz 1:88200 Hz 2:64000 Hz 3:48000 Hz 4:44100 Hz 5:32000 Hz 6:24000 Hz 7:22050 Hz 8:16000 Hz 9:12000 Hz 10:11025 Hz 11:8000 Hz 12:7350 Hz 13:reserved 14:reserved 15:frequency is written explictly */In    T idx = 4;    if (samplerate >= 7350 && samplerate < 8000) {idx = 12;    } else if (samplerate >= 8000 && samplerate < 11025) {idx = 11;    } else if (samplerate >= 11025 && samplerate < 12000) {idx = 10;    } else if (samplerate >= 12000 && samplerate < 16000) {idx = 9;    } else if (samplerate >= 16000 && samplerate < 22050) {idx = 8;    } else if (samplerate >= 22050 && samplerate < 24000) {idx = 7;    } else if (samplerate >= 24000 && samplerate < 32000) {idx = 6;    } else if (samplerate >= 32000 && samplerate < 44100) {idx = 5;    } else if (samplerate >= 44100 && samplerate < 48000) {idx = 4; } else if (samplerate >= 48000 &&    Samplerate < 64000) {idx = 3;    } else if (samplerate >= 64000 && samplerate < 88200) {idx = 2;    } else if (samplerate >= 88200 && samplerate < 96000) {idx = 1;    } else if (samplerate >= 96000) {idx = 0; } return idx;}     int channelidxforadtsheader (int channelcount) {/** 0:defined in AOT specifc Config 1:1 channel:front-center 2:2 channels:front-left, Front-right 3:3 channels:front-center, Front-left, Front-right 4:4 Channels:fro Nt-center, Front-left, Front-right, Back-center 5:5 channels:front-center, Front-left, Front-right, Back-left, back- Right 6:6 Channels:front-center, Front-left, Front-right, Back-left, Back-right, Lfe-channel 7:8 Channels:fron    T-center, Front-left, Front-right, Side-left, Side-right, Back-left, Back-right, lfe-channel 8-15:reserved * *    int ret = 2;    if (Channelcount = = 1) {ret = 1; } else if (ChannelcouNT = = 2) {ret = 2; } return ret;} /** * ADD ADTS header at the beginning for each and every AAC packet. * This is needed as MEDIACODEC encoder generates a packet of raw * AAC data. * * Note The Packetlen must count in the ADTS header itself. * See:http://wiki.multimedia.cx/index.php?title=adts * also:http://wiki.multimedia.cx/index.php?title=mpeg-4_ Audio#channel_configurations **/char* newadtsdataforpacketlength (int packetlength, int samplerate, int channelCount,    int* ioheaderlen) {int adtslength = 7;    Char *packet = malloc (sizeof (char) * adtslength);  Variables Recycled by addadtstopacket int profile = 2;    AAC LC//39=mediacodecinfo.codecprofilelevel.aacobjecteld;    int freqidx = Freqidxforadtsheader (samplerate);  int chancfg = Channelidxforadtsheader (Channelcount);    MPEG-4 Audio Channel Configuration.    Nsuinteger fulllength = adtslength + packetlength; Fill in ADTS data packet[0] = (char) 0xff;//11111111 = Syncword packet[1]= (char) 0xf9;//1111 1 xx 1 = Syncword MPEG-2 Layer CRC packet[2] = (char) (((profile-1) <<6) + (FREQIDX&LT;&LT;2)    + (CHANCFG&GT;&GT;2));    PACKET[3] = (char) (((chancfg&3) <<6) + (fulllength>>11));    PACKET[4] = (char) ((FULLLENGTH&AMP;0X7FF) >> 3);    PACKET[5] = (char) (((fulllength&7) <<5) + 0x1F);    PACKET[6] = (char) 0xFC;    *ioheaderlen = Adtslength; return packet;}

The above code, there are two functions are important, one is the initialization function, the function created Audioconverterref, and the other is a conversion function, this function should be repeatedly called, the different PCM data conversion.

Also, in the example, the AAC data converted from PCM is saved, and the saved files can be used for playback.

Note that the Audioconverter conversion is all audio raw data, as for the combination of ADTS-AAC, or packaged into Apple M4A file, determined by the program.

As explained here, ADTS-AAC is a representation of AAC data, that is, in front of each frame of AAC bare data, the addition of a frame information (including the length of each frame, sample rate, number of channels, etc.), plus the frame information, each frame AAC can be played separately. Moreover, ADTS-AAC is not encapsulated, that is, there is no specific file header and file structure.

Adts is an abbreviation for audio Data Transport stream.

Of course, the reader can also put the converted AAC data into M4A format, this encapsulation format, first the file header, then the Naked audio data:

{packet-table} {Audio_data} {trailer}, after the header information is the audio raw data, audio data without packet information.

At this point, the iOS platform to convert the PCM into AAC data implementation is complete.

To summarize, this article describes how to use the Audioconverter interface provided by the iOS platform to convert data in PCM format into AAC format. The article also describes how to save the Adts-aac file, the reader can use this method to verify that the converted AAC data is correct.

Audio encoded into AAC on iOS platform

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.