[{"data":1,"prerenderedAt":2034},["ShallowReactive",2],{"article_list_cocoa_":3},[4],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"publishDate":11,"tags":12,"image":16,"excerpt":10,"body":17,"_type":2025,"_id":2026,"_source":2027,"_file":2028,"_stem":2029,"_extension":2030,"author":2031},"/shuey/2012-07/mixer","2012-07",false,"","A Simple Mixer Using AVFoundation","In iOS 4.0 Apple introduced the AV Foundation APIs that made working with audio and video media much easier than it had been in previous versions of iOS. Apple then brought these APIs to Mac OS X in OS X 10.7 \"Lion\". In this post I'll show how to use some of the APIs to create a simple four track mixer.","2012-07-02",[13,14,15],"apple","cocoa","ios","/shuey/2012-07/img/mixer-screenshot.jpg",{"type":18,"children":19,"toc":2023},"root",[20,39,71,80,103,126,1071,1094,1102,1290,1295,1303,1476,1481,1489,1592,1597,1605,1976,1999,2007,2012,2017],{"type":21,"tag":22,"props":23,"children":24},"element","p",{},[25,28,37],{"type":26,"value":27},"text","In iOS 4.0 Apple introduced the ",{"type":21,"tag":29,"props":30,"children":34},"a",{"href":31,"rel":32},"https://developer.apple.com/library/mac/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188",[33],"nofollow",[35],{"type":26,"value":36},"AV Foundation APIs",{"type":26,"value":38}," that made working with audio and video media much easier than it had been in previous versions of iOS. Apple then brought these APIs to Mac OS X in OS X 10.7 \"Lion\". In this post I'll show how to use some of the APIs to create a simple four track mixer.",{"type":21,"tag":22,"props":40,"children":41},{},[42,44,51,53,60,62,69],{"type":26,"value":43},"The code for the project is ",{"type":21,"tag":29,"props":45,"children":48},{"href":46,"rel":47},"https://github.com/stevenhuey/ALMixer",[33],[49],{"type":26,"value":50},"available on GitHub",{"type":26,"value":52},". You'll need to provide your own audio files. The project is setup to use four WAV files named track1.wav - track4.wav but the ",{"type":21,"tag":29,"props":54,"children":57},{"href":55,"rel":56},"https://github.com/stevenhuey/ALMixer/blob/master/README.md",[33],[58],{"type":26,"value":59},"ReadMe.md",{"type":26,"value":61}," lists the two lines of code you need to change to use another audio format or naming scheme. Obviously you need to use an audio format supported by iOS. The project is configured to use ",{"type":21,"tag":29,"props":63,"children":66},{"href":64,"rel":65},"https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226",[33],[67],{"type":26,"value":68},"ARC",{"type":26,"value":70}," (Automatic Reference Counting).",{"type":21,"tag":22,"props":72,"children":73},{},[74],{"type":21,"tag":75,"props":76,"children":77},"strong",{},[78],{"type":26,"value":79},"Setup",{"type":21,"tag":22,"props":81,"children":82},{},[83,85,92,94,101],{"type":26,"value":84},"To start we'll create an ",{"type":21,"tag":29,"props":86,"children":89},{"href":87,"rel":88},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableComposition_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40009526",[33],[90],{"type":26,"value":91},"AVMutableComposition",{"type":26,"value":93}," instance and two ",{"type":21,"tag":29,"props":95,"children":98},{"href":96,"rel":97},"https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/Reference/Reference.html",[33],[99],{"type":26,"value":100},"NSMutableDictionaries",{"type":26,"value":102},". We'll use the dictionaries for keeping track of the IDs assigned to the audio tracks by the AVFoundation framework and for storing the volume level of each track.",{"type":21,"tag":22,"props":104,"children":105},{},[106,108,115,117,124],{"type":26,"value":107},"Our audio tracks are loaded from the Resources directory within the app bundle using the ",{"type":21,"tag":29,"props":109,"children":112},{"href":110,"rel":111},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVURLAsset_Class/Reference/Reference.html",[33],[113],{"type":26,"value":114},"AVURLAsset",{"type":26,"value":116}," class and then used to create an ",{"type":21,"tag":29,"props":118,"children":121},{"href":119,"rel":120},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableCompositionTrack_Class/Reference/Reference.html",[33],[122],{"type":26,"value":123},"AVMutableCompositionTrack",{"type":26,"value":125}," that we insert into our AVMutableComposition. We record the ID of the track and set the track volume to 1.0, the maximum. The volume for each track can be set from 0.0 - 1.0.",{"type":21,"tag":127,"props":128,"children":132},"pre",{"className":129,"code":130,"language":131,"meta":8,"style":8},"language-swift shiki shiki-themes github-light github-dark","// Setup\n   _composition = [AVMutableComposition composition];\n\n   _audioMixValues = [[NSMutableDictionary alloc] initWithCapacity:0];\n   _audioMixTrackIDs = [[NSMutableDictionary alloc] initWithCapacity:0];\n\n   // Insert the audio tracks into our composition\n   NSArray* tracks = [NSArray arrayWithObjects:@\"track1\", @\"track2\", @\"track3\", @\"track4\", nil];\n   NSString* audioFileType = @\"wav\";\n\n   for (NSString* trackName in tracks)\n   {\n      AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:trackName ofType:audioFileType]]\n                                                      options:nil];\n\n      AVMutableCompositionTrack* audioTrack = [_composition addMutableTrackWithMediaType:AVMediaTypeAudio\n                                                                        preferredTrackID:kCMPersistentTrackID_Invalid];\n\n      NSError* error;\n      [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration)\n                          ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0]\n                           atTime:kCMTimeZero\n                            error:&error];\n\n      if (error)\n      {\n         NSLog(@\"%@\", [error localizedDescription]);\n      }\n\n      // Store the track IDs as track name -> track ID\n      [_audioMixTrackIDs setValue:[NSNumber numberWithInteger:audioTrack.trackID]\n                           forKey:trackName];\n\n      // Set the volume to 1.0 (max) for the track\n      [self setVolume:1.0f forTrack:trackName];\n   }\n\n   // Create a player for our composition of audio tracks. We observe the status so\n   // we know when the player is ready to play\n   AVPlayerItem* playerItem = [[AVPlayerItem alloc] initWithAsset:[_composition copy]];\n   [playerItem addObserver:self\n                forKeyPath:@\"status\"\n                   options:0\n                   context:NULL];\n\n   _player = [[AVPlayer alloc] initWithPlayerItem:playerItem];\n","swift",[133],{"type":21,"tag":134,"props":135,"children":136},"code",{"__ignoreMap":8},[137,149,170,180,214,243,251,260,345,382,390,423,432,495,516,524,560,578,586,604,627,667,685,704,712,726,735,759,768,776,785,812,830,838,847,889,898,906,915,924,960,978,1000,1018,1036,1044],{"type":21,"tag":138,"props":139,"children":142},"span",{"class":140,"line":141},"line",1,[143],{"type":21,"tag":138,"props":144,"children":146},{"style":145},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[147],{"type":26,"value":148},"// Setup\n",{"type":21,"tag":138,"props":150,"children":152},{"class":140,"line":151},2,[153,159,165],{"type":21,"tag":138,"props":154,"children":156},{"style":155},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[157],{"type":26,"value":158},"   _composition ",{"type":21,"tag":138,"props":160,"children":162},{"style":161},"--shiki-default:#D73A49;--shiki-dark:#F97583",[163],{"type":26,"value":164},"=",{"type":21,"tag":138,"props":166,"children":167},{"style":155},[168],{"type":26,"value":169}," [AVMutableComposition composition];\n",{"type":21,"tag":138,"props":171,"children":173},{"class":140,"line":172},3,[174],{"type":21,"tag":138,"props":175,"children":177},{"emptyLinePlaceholder":176},true,[178],{"type":26,"value":179},"\n",{"type":21,"tag":138,"props":181,"children":183},{"class":140,"line":182},4,[184,189,193,198,203,209],{"type":21,"tag":138,"props":185,"children":186},{"style":155},[187],{"type":26,"value":188},"   _audioMixValues ",{"type":21,"tag":138,"props":190,"children":191},{"style":161},[192],{"type":26,"value":164},{"type":21,"tag":138,"props":194,"children":195},{"style":155},[196],{"type":26,"value":197}," [[NSMutableDictionary alloc] initWithCapacity",{"type":21,"tag":138,"props":199,"children":200},{"style":161},[201],{"type":26,"value":202},":",{"type":21,"tag":138,"props":204,"children":206},{"style":205},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[207],{"type":26,"value":208},"0",{"type":21,"tag":138,"props":210,"children":211},{"style":155},[212],{"type":26,"value":213},"];\n",{"type":21,"tag":138,"props":215,"children":217},{"class":140,"line":216},5,[218,223,227,231,235,239],{"type":21,"tag":138,"props":219,"children":220},{"style":155},[221],{"type":26,"value":222},"   _audioMixTrackIDs ",{"type":21,"tag":138,"props":224,"children":225},{"style":161},[226],{"type":26,"value":164},{"type":21,"tag":138,"props":228,"children":229},{"style":155},[230],{"type":26,"value":197},{"type":21,"tag":138,"props":232,"children":233},{"style":161},[234],{"type":26,"value":202},{"type":21,"tag":138,"props":236,"children":237},{"style":205},[238],{"type":26,"value":208},{"type":21,"tag":138,"props":240,"children":241},{"style":155},[242],{"type":26,"value":213},{"type":21,"tag":138,"props":244,"children":246},{"class":140,"line":245},6,[247],{"type":21,"tag":138,"props":248,"children":249},{"emptyLinePlaceholder":176},[250],{"type":26,"value":179},{"type":21,"tag":138,"props":252,"children":254},{"class":140,"line":253},7,[255],{"type":21,"tag":138,"props":256,"children":257},{"style":145},[258],{"type":26,"value":259},"   // Insert the audio tracks into our composition\n",{"type":21,"tag":138,"props":261,"children":263},{"class":140,"line":262},8,[264,269,274,279,283,288,292,297,303,308,313,317,322,326,331,336,341],{"type":21,"tag":138,"props":265,"children":266},{"style":155},[267],{"type":26,"value":268},"   NSArray",{"type":21,"tag":138,"props":270,"children":271},{"style":161},[272],{"type":26,"value":273},"*",{"type":21,"tag":138,"props":275,"children":276},{"style":155},[277],{"type":26,"value":278}," tracks ",{"type":21,"tag":138,"props":280,"children":281},{"style":161},[282],{"type":26,"value":164},{"type":21,"tag":138,"props":284,"children":285},{"style":155},[286],{"type":26,"value":287}," [NSArray arrayWithObjects",{"type":21,"tag":138,"props":289,"children":290},{"style":161},[291],{"type":26,"value":202},{"type":21,"tag":138,"props":293,"children":294},{"style":155},[295],{"type":26,"value":296},"@",{"type":21,"tag":138,"props":298,"children":300},{"style":299},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[301],{"type":26,"value":302},"\"track1\"",{"type":21,"tag":138,"props":304,"children":305},{"style":155},[306],{"type":26,"value":307},", @",{"type":21,"tag":138,"props":309,"children":310},{"style":299},[311],{"type":26,"value":312},"\"track2\"",{"type":21,"tag":138,"props":314,"children":315},{"style":155},[316],{"type":26,"value":307},{"type":21,"tag":138,"props":318,"children":319},{"style":299},[320],{"type":26,"value":321},"\"track3\"",{"type":21,"tag":138,"props":323,"children":324},{"style":155},[325],{"type":26,"value":307},{"type":21,"tag":138,"props":327,"children":328},{"style":299},[329],{"type":26,"value":330},"\"track4\"",{"type":21,"tag":138,"props":332,"children":333},{"style":155},[334],{"type":26,"value":335},", ",{"type":21,"tag":138,"props":337,"children":338},{"style":205},[339],{"type":26,"value":340},"nil",{"type":21,"tag":138,"props":342,"children":343},{"style":155},[344],{"type":26,"value":213},{"type":21,"tag":138,"props":346,"children":348},{"class":140,"line":347},9,[349,354,358,363,367,372,377],{"type":21,"tag":138,"props":350,"children":351},{"style":155},[352],{"type":26,"value":353},"   NSString",{"type":21,"tag":138,"props":355,"children":356},{"style":161},[357],{"type":26,"value":273},{"type":21,"tag":138,"props":359,"children":360},{"style":155},[361],{"type":26,"value":362}," audioFileType ",{"type":21,"tag":138,"props":364,"children":365},{"style":161},[366],{"type":26,"value":164},{"type":21,"tag":138,"props":368,"children":369},{"style":155},[370],{"type":26,"value":371}," @",{"type":21,"tag":138,"props":373,"children":374},{"style":299},[375],{"type":26,"value":376},"\"wav\"",{"type":21,"tag":138,"props":378,"children":379},{"style":155},[380],{"type":26,"value":381},";\n",{"type":21,"tag":138,"props":383,"children":385},{"class":140,"line":384},10,[386],{"type":21,"tag":138,"props":387,"children":388},{"emptyLinePlaceholder":176},[389],{"type":26,"value":179},{"type":21,"tag":138,"props":391,"children":393},{"class":140,"line":392},11,[394,399,404,408,413,418],{"type":21,"tag":138,"props":395,"children":396},{"style":161},[397],{"type":26,"value":398},"   for",{"type":21,"tag":138,"props":400,"children":401},{"style":155},[402],{"type":26,"value":403}," (NSString",{"type":21,"tag":138,"props":405,"children":406},{"style":161},[407],{"type":26,"value":273},{"type":21,"tag":138,"props":409,"children":410},{"style":155},[411],{"type":26,"value":412}," trackName ",{"type":21,"tag":138,"props":414,"children":415},{"style":161},[416],{"type":26,"value":417},"in",{"type":21,"tag":138,"props":419,"children":420},{"style":155},[421],{"type":26,"value":422}," tracks)\n",{"type":21,"tag":138,"props":424,"children":426},{"class":140,"line":425},12,[427],{"type":21,"tag":138,"props":428,"children":429},{"style":155},[430],{"type":26,"value":431},"   {\n",{"type":21,"tag":138,"props":433,"children":435},{"class":140,"line":434},13,[436,441,445,450,454,459,463,468,472,477,481,486,490],{"type":21,"tag":138,"props":437,"children":438},{"style":155},[439],{"type":26,"value":440},"      AVURLAsset",{"type":21,"tag":138,"props":442,"children":443},{"style":161},[444],{"type":26,"value":273},{"type":21,"tag":138,"props":446,"children":447},{"style":155},[448],{"type":26,"value":449}," audioAsset ",{"type":21,"tag":138,"props":451,"children":452},{"style":161},[453],{"type":26,"value":164},{"type":21,"tag":138,"props":455,"children":456},{"style":155},[457],{"type":26,"value":458}," [[AVURLAsset alloc]initWithURL",{"type":21,"tag":138,"props":460,"children":461},{"style":161},[462],{"type":26,"value":202},{"type":21,"tag":138,"props":464,"children":465},{"style":155},[466],{"type":26,"value":467},"[NSURL fileURLWithPath",{"type":21,"tag":138,"props":469,"children":470},{"style":161},[471],{"type":26,"value":202},{"type":21,"tag":138,"props":473,"children":474},{"style":155},[475],{"type":26,"value":476},"[[NSBundle mainBundle] pathForResource",{"type":21,"tag":138,"props":478,"children":479},{"style":161},[480],{"type":26,"value":202},{"type":21,"tag":138,"props":482,"children":483},{"style":155},[484],{"type":26,"value":485},"trackName ofType",{"type":21,"tag":138,"props":487,"children":488},{"style":161},[489],{"type":26,"value":202},{"type":21,"tag":138,"props":491,"children":492},{"style":155},[493],{"type":26,"value":494},"audioFileType]]\n",{"type":21,"tag":138,"props":496,"children":498},{"class":140,"line":497},14,[499,504,508,512],{"type":21,"tag":138,"props":500,"children":501},{"style":155},[502],{"type":26,"value":503},"                                                      options",{"type":21,"tag":138,"props":505,"children":506},{"style":161},[507],{"type":26,"value":202},{"type":21,"tag":138,"props":509,"children":510},{"style":205},[511],{"type":26,"value":340},{"type":21,"tag":138,"props":513,"children":514},{"style":155},[515],{"type":26,"value":213},{"type":21,"tag":138,"props":517,"children":519},{"class":140,"line":518},15,[520],{"type":21,"tag":138,"props":521,"children":522},{"emptyLinePlaceholder":176},[523],{"type":26,"value":179},{"type":21,"tag":138,"props":525,"children":527},{"class":140,"line":526},16,[528,533,537,542,546,551,555],{"type":21,"tag":138,"props":529,"children":530},{"style":155},[531],{"type":26,"value":532},"      AVMutableCompositionTrack",{"type":21,"tag":138,"props":534,"children":535},{"style":161},[536],{"type":26,"value":273},{"type":21,"tag":138,"props":538,"children":539},{"style":155},[540],{"type":26,"value":541}," audioTrack ",{"type":21,"tag":138,"props":543,"children":544},{"style":161},[545],{"type":26,"value":164},{"type":21,"tag":138,"props":547,"children":548},{"style":155},[549],{"type":26,"value":550}," [_composition addMutableTrackWithMediaType",{"type":21,"tag":138,"props":552,"children":553},{"style":161},[554],{"type":26,"value":202},{"type":21,"tag":138,"props":556,"children":557},{"style":155},[558],{"type":26,"value":559},"AVMediaTypeAudio\n",{"type":21,"tag":138,"props":561,"children":563},{"class":140,"line":562},17,[564,569,573],{"type":21,"tag":138,"props":565,"children":566},{"style":155},[567],{"type":26,"value":568},"                                                                        preferredTrackID",{"type":21,"tag":138,"props":570,"children":571},{"style":161},[572],{"type":26,"value":202},{"type":21,"tag":138,"props":574,"children":575},{"style":155},[576],{"type":26,"value":577},"kCMPersistentTrackID_Invalid];\n",{"type":21,"tag":138,"props":579,"children":581},{"class":140,"line":580},18,[582],{"type":21,"tag":138,"props":583,"children":584},{"emptyLinePlaceholder":176},[585],{"type":26,"value":179},{"type":21,"tag":138,"props":587,"children":589},{"class":140,"line":588},19,[590,595,599],{"type":21,"tag":138,"props":591,"children":592},{"style":155},[593],{"type":26,"value":594},"      NSError",{"type":21,"tag":138,"props":596,"children":597},{"style":161},[598],{"type":26,"value":273},{"type":21,"tag":138,"props":600,"children":601},{"style":155},[602],{"type":26,"value":603}," error;\n",{"type":21,"tag":138,"props":605,"children":607},{"class":140,"line":606},20,[608,613,617,622],{"type":21,"tag":138,"props":609,"children":610},{"style":155},[611],{"type":26,"value":612},"      [audioTrack insertTimeRange",{"type":21,"tag":138,"props":614,"children":615},{"style":161},[616],{"type":26,"value":202},{"type":21,"tag":138,"props":618,"children":619},{"style":205},[620],{"type":26,"value":621},"CMTimeRangeMake",{"type":21,"tag":138,"props":623,"children":624},{"style":155},[625],{"type":26,"value":626},"(kCMTimeZero, audioAsset.duration)\n",{"type":21,"tag":138,"props":628,"children":630},{"class":140,"line":629},21,[631,636,640,645,649,654,658,662],{"type":21,"tag":138,"props":632,"children":633},{"style":155},[634],{"type":26,"value":635},"                          ofTrack",{"type":21,"tag":138,"props":637,"children":638},{"style":161},[639],{"type":26,"value":202},{"type":21,"tag":138,"props":641,"children":642},{"style":155},[643],{"type":26,"value":644},"[[audioAsset tracksWithMediaType",{"type":21,"tag":138,"props":646,"children":647},{"style":161},[648],{"type":26,"value":202},{"type":21,"tag":138,"props":650,"children":651},{"style":155},[652],{"type":26,"value":653},"AVMediaTypeAudio]objectAtIndex",{"type":21,"tag":138,"props":655,"children":656},{"style":161},[657],{"type":26,"value":202},{"type":21,"tag":138,"props":659,"children":660},{"style":205},[661],{"type":26,"value":208},{"type":21,"tag":138,"props":663,"children":664},{"style":155},[665],{"type":26,"value":666},"]\n",{"type":21,"tag":138,"props":668,"children":670},{"class":140,"line":669},22,[671,676,680],{"type":21,"tag":138,"props":672,"children":673},{"style":155},[674],{"type":26,"value":675},"                           atTime",{"type":21,"tag":138,"props":677,"children":678},{"style":161},[679],{"type":26,"value":202},{"type":21,"tag":138,"props":681,"children":682},{"style":155},[683],{"type":26,"value":684},"kCMTimeZero\n",{"type":21,"tag":138,"props":686,"children":688},{"class":140,"line":687},23,[689,694,699],{"type":21,"tag":138,"props":690,"children":691},{"style":155},[692],{"type":26,"value":693},"                            error",{"type":21,"tag":138,"props":695,"children":696},{"style":161},[697],{"type":26,"value":698},":&",{"type":21,"tag":138,"props":700,"children":701},{"style":155},[702],{"type":26,"value":703},"error];\n",{"type":21,"tag":138,"props":705,"children":707},{"class":140,"line":706},24,[708],{"type":21,"tag":138,"props":709,"children":710},{"emptyLinePlaceholder":176},[711],{"type":26,"value":179},{"type":21,"tag":138,"props":713,"children":715},{"class":140,"line":714},25,[716,721],{"type":21,"tag":138,"props":717,"children":718},{"style":161},[719],{"type":26,"value":720},"      if",{"type":21,"tag":138,"props":722,"children":723},{"style":155},[724],{"type":26,"value":725}," (error)\n",{"type":21,"tag":138,"props":727,"children":729},{"class":140,"line":728},26,[730],{"type":21,"tag":138,"props":731,"children":732},{"style":155},[733],{"type":26,"value":734},"      {\n",{"type":21,"tag":138,"props":736,"children":738},{"class":140,"line":737},27,[739,744,749,754],{"type":21,"tag":138,"props":740,"children":741},{"style":205},[742],{"type":26,"value":743},"         NSLog",{"type":21,"tag":138,"props":745,"children":746},{"style":155},[747],{"type":26,"value":748},"(@",{"type":21,"tag":138,"props":750,"children":751},{"style":299},[752],{"type":26,"value":753},"\"%@\"",{"type":21,"tag":138,"props":755,"children":756},{"style":155},[757],{"type":26,"value":758},", [error localizedDescription]);\n",{"type":21,"tag":138,"props":760,"children":762},{"class":140,"line":761},28,[763],{"type":21,"tag":138,"props":764,"children":765},{"style":155},[766],{"type":26,"value":767},"      }\n",{"type":21,"tag":138,"props":769,"children":771},{"class":140,"line":770},29,[772],{"type":21,"tag":138,"props":773,"children":774},{"emptyLinePlaceholder":176},[775],{"type":26,"value":179},{"type":21,"tag":138,"props":777,"children":779},{"class":140,"line":778},30,[780],{"type":21,"tag":138,"props":781,"children":782},{"style":145},[783],{"type":26,"value":784},"      // Store the track IDs as track name -> track ID\n",{"type":21,"tag":138,"props":786,"children":788},{"class":140,"line":787},31,[789,794,798,803,807],{"type":21,"tag":138,"props":790,"children":791},{"style":155},[792],{"type":26,"value":793},"      [_audioMixTrackIDs setValue",{"type":21,"tag":138,"props":795,"children":796},{"style":161},[797],{"type":26,"value":202},{"type":21,"tag":138,"props":799,"children":800},{"style":155},[801],{"type":26,"value":802},"[NSNumber numberWithInteger",{"type":21,"tag":138,"props":804,"children":805},{"style":161},[806],{"type":26,"value":202},{"type":21,"tag":138,"props":808,"children":809},{"style":155},[810],{"type":26,"value":811},"audioTrack.trackID]\n",{"type":21,"tag":138,"props":813,"children":815},{"class":140,"line":814},32,[816,821,825],{"type":21,"tag":138,"props":817,"children":818},{"style":155},[819],{"type":26,"value":820},"                           forKey",{"type":21,"tag":138,"props":822,"children":823},{"style":161},[824],{"type":26,"value":202},{"type":21,"tag":138,"props":826,"children":827},{"style":155},[828],{"type":26,"value":829},"trackName];\n",{"type":21,"tag":138,"props":831,"children":833},{"class":140,"line":832},33,[834],{"type":21,"tag":138,"props":835,"children":836},{"emptyLinePlaceholder":176},[837],{"type":26,"value":179},{"type":21,"tag":138,"props":839,"children":841},{"class":140,"line":840},34,[842],{"type":21,"tag":138,"props":843,"children":844},{"style":145},[845],{"type":26,"value":846},"      // Set the volume to 1.0 (max) for the track\n",{"type":21,"tag":138,"props":848,"children":850},{"class":140,"line":849},35,[851,856,861,866,870,876,881,885],{"type":21,"tag":138,"props":852,"children":853},{"style":155},[854],{"type":26,"value":855},"      [",{"type":21,"tag":138,"props":857,"children":858},{"style":205},[859],{"type":26,"value":860},"self",{"type":21,"tag":138,"props":862,"children":863},{"style":155},[864],{"type":26,"value":865}," setVolume",{"type":21,"tag":138,"props":867,"children":868},{"style":161},[869],{"type":26,"value":202},{"type":21,"tag":138,"props":871,"children":873},{"style":872},"--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic",[874],{"type":26,"value":875},"1.0f",{"type":21,"tag":138,"props":877,"children":878},{"style":155},[879],{"type":26,"value":880}," forTrack",{"type":21,"tag":138,"props":882,"children":883},{"style":161},[884],{"type":26,"value":202},{"type":21,"tag":138,"props":886,"children":887},{"style":155},[888],{"type":26,"value":829},{"type":21,"tag":138,"props":890,"children":892},{"class":140,"line":891},36,[893],{"type":21,"tag":138,"props":894,"children":895},{"style":155},[896],{"type":26,"value":897},"   }\n",{"type":21,"tag":138,"props":899,"children":901},{"class":140,"line":900},37,[902],{"type":21,"tag":138,"props":903,"children":904},{"emptyLinePlaceholder":176},[905],{"type":26,"value":179},{"type":21,"tag":138,"props":907,"children":909},{"class":140,"line":908},38,[910],{"type":21,"tag":138,"props":911,"children":912},{"style":145},[913],{"type":26,"value":914},"   // Create a player for our composition of audio tracks. We observe the status so\n",{"type":21,"tag":138,"props":916,"children":918},{"class":140,"line":917},39,[919],{"type":21,"tag":138,"props":920,"children":921},{"style":145},[922],{"type":26,"value":923},"   // we know when the player is ready to play\n",{"type":21,"tag":138,"props":925,"children":927},{"class":140,"line":926},40,[928,933,937,942,946,951,955],{"type":21,"tag":138,"props":929,"children":930},{"style":155},[931],{"type":26,"value":932},"   AVPlayerItem",{"type":21,"tag":138,"props":934,"children":935},{"style":161},[936],{"type":26,"value":273},{"type":21,"tag":138,"props":938,"children":939},{"style":155},[940],{"type":26,"value":941}," playerItem ",{"type":21,"tag":138,"props":943,"children":944},{"style":161},[945],{"type":26,"value":164},{"type":21,"tag":138,"props":947,"children":948},{"style":155},[949],{"type":26,"value":950}," [[AVPlayerItem alloc] initWithAsset",{"type":21,"tag":138,"props":952,"children":953},{"style":161},[954],{"type":26,"value":202},{"type":21,"tag":138,"props":956,"children":957},{"style":155},[958],{"type":26,"value":959},"[_composition copy]];\n",{"type":21,"tag":138,"props":961,"children":963},{"class":140,"line":962},41,[964,969,973],{"type":21,"tag":138,"props":965,"children":966},{"style":155},[967],{"type":26,"value":968},"   [playerItem addObserver",{"type":21,"tag":138,"props":970,"children":971},{"style":161},[972],{"type":26,"value":202},{"type":21,"tag":138,"props":974,"children":975},{"style":205},[976],{"type":26,"value":977},"self\n",{"type":21,"tag":138,"props":979,"children":981},{"class":140,"line":980},42,[982,987,991,995],{"type":21,"tag":138,"props":983,"children":984},{"style":155},[985],{"type":26,"value":986},"                forKeyPath",{"type":21,"tag":138,"props":988,"children":989},{"style":161},[990],{"type":26,"value":202},{"type":21,"tag":138,"props":992,"children":993},{"style":155},[994],{"type":26,"value":296},{"type":21,"tag":138,"props":996,"children":997},{"style":299},[998],{"type":26,"value":999},"\"status\"\n",{"type":21,"tag":138,"props":1001,"children":1003},{"class":140,"line":1002},43,[1004,1009,1013],{"type":21,"tag":138,"props":1005,"children":1006},{"style":155},[1007],{"type":26,"value":1008},"                   options",{"type":21,"tag":138,"props":1010,"children":1011},{"style":161},[1012],{"type":26,"value":202},{"type":21,"tag":138,"props":1014,"children":1015},{"style":205},[1016],{"type":26,"value":1017},"0\n",{"type":21,"tag":138,"props":1019,"children":1021},{"class":140,"line":1020},44,[1022,1027,1031],{"type":21,"tag":138,"props":1023,"children":1024},{"style":155},[1025],{"type":26,"value":1026},"                   context",{"type":21,"tag":138,"props":1028,"children":1029},{"style":161},[1030],{"type":26,"value":202},{"type":21,"tag":138,"props":1032,"children":1033},{"style":155},[1034],{"type":26,"value":1035},"NULL];\n",{"type":21,"tag":138,"props":1037,"children":1039},{"class":140,"line":1038},45,[1040],{"type":21,"tag":138,"props":1041,"children":1042},{"emptyLinePlaceholder":176},[1043],{"type":26,"value":179},{"type":21,"tag":138,"props":1045,"children":1047},{"class":140,"line":1046},46,[1048,1053,1057,1062,1066],{"type":21,"tag":138,"props":1049,"children":1050},{"style":155},[1051],{"type":26,"value":1052},"   _player ",{"type":21,"tag":138,"props":1054,"children":1055},{"style":161},[1056],{"type":26,"value":164},{"type":21,"tag":138,"props":1058,"children":1059},{"style":155},[1060],{"type":26,"value":1061}," [[AVPlayer alloc] initWithPlayerItem",{"type":21,"tag":138,"props":1063,"children":1064},{"style":161},[1065],{"type":26,"value":202},{"type":21,"tag":138,"props":1067,"children":1068},{"style":155},[1069],{"type":26,"value":1070},"playerItem];\n",{"type":21,"tag":22,"props":1072,"children":1073},{},[1074,1076,1083,1085,1092],{"type":26,"value":1075},"Finally, we create an ",{"type":21,"tag":29,"props":1077,"children":1080},{"href":1078,"rel":1079},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayerItem_Class/Reference/Reference.html",[33],[1081],{"type":26,"value":1082},"AVPlayerItem",{"type":26,"value":1084}," using our AVMutableComposition, and use that to create a ",{"type":21,"tag":29,"props":1086,"children":1089},{"href":1087,"rel":1088},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayer_Class/Reference/Reference.html",[33],[1090],{"type":26,"value":1091},"AVPlayer",{"type":26,"value":1093}," that we'll use to control playback of the composition. We also want to observe the \"status\" key of our player item to be notified of changes in the state of our AVPlayerItem.",{"type":21,"tag":22,"props":1095,"children":1096},{},[1097],{"type":21,"tag":75,"props":1098,"children":1099},{},[1100],{"type":26,"value":1101},"Key Value Observing (KVO)",{"type":21,"tag":127,"props":1103,"children":1105},{"className":129,"code":1104,"language":131,"meta":8,"style":8},"- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context\n{\n   if ([keyPath isEqualToString:@\"status\"])\n   {\n      if (AVPlayerItemStatusReadyToPlay == _player.currentItem.status)\n      {\n         [_player play];\n      }\n   }\n}\n",[1106],{"type":21,"tag":134,"props":1107,"children":1108},{"__ignoreMap":8},[1109,1185,1193,1224,1231,1253,1260,1268,1275,1282],{"type":21,"tag":138,"props":1110,"children":1111},{"class":140,"line":141},[1112,1117,1122,1126,1131,1135,1140,1144,1149,1153,1158,1162,1167,1171,1176,1180],{"type":21,"tag":138,"props":1113,"children":1114},{"style":161},[1115],{"type":26,"value":1116},"-",{"type":21,"tag":138,"props":1118,"children":1119},{"style":155},[1120],{"type":26,"value":1121}," (void)observeValueForKeyPath",{"type":21,"tag":138,"props":1123,"children":1124},{"style":161},[1125],{"type":26,"value":202},{"type":21,"tag":138,"props":1127,"children":1128},{"style":155},[1129],{"type":26,"value":1130},"(NSString ",{"type":21,"tag":138,"props":1132,"children":1133},{"style":161},[1134],{"type":26,"value":273},{"type":21,"tag":138,"props":1136,"children":1137},{"style":155},[1138],{"type":26,"value":1139},")keyPath ofObject",{"type":21,"tag":138,"props":1141,"children":1142},{"style":161},[1143],{"type":26,"value":202},{"type":21,"tag":138,"props":1145,"children":1146},{"style":155},[1147],{"type":26,"value":1148},"(id)object change",{"type":21,"tag":138,"props":1150,"children":1151},{"style":161},[1152],{"type":26,"value":202},{"type":21,"tag":138,"props":1154,"children":1155},{"style":155},[1156],{"type":26,"value":1157},"(NSDictionary ",{"type":21,"tag":138,"props":1159,"children":1160},{"style":161},[1161],{"type":26,"value":273},{"type":21,"tag":138,"props":1163,"children":1164},{"style":155},[1165],{"type":26,"value":1166},")change context",{"type":21,"tag":138,"props":1168,"children":1169},{"style":161},[1170],{"type":26,"value":202},{"type":21,"tag":138,"props":1172,"children":1173},{"style":155},[1174],{"type":26,"value":1175},"(void ",{"type":21,"tag":138,"props":1177,"children":1178},{"style":161},[1179],{"type":26,"value":273},{"type":21,"tag":138,"props":1181,"children":1182},{"style":155},[1183],{"type":26,"value":1184},")context\n",{"type":21,"tag":138,"props":1186,"children":1187},{"class":140,"line":151},[1188],{"type":21,"tag":138,"props":1189,"children":1190},{"style":155},[1191],{"type":26,"value":1192},"{\n",{"type":21,"tag":138,"props":1194,"children":1195},{"class":140,"line":172},[1196,1201,1206,1210,1214,1219],{"type":21,"tag":138,"props":1197,"children":1198},{"style":161},[1199],{"type":26,"value":1200},"   if",{"type":21,"tag":138,"props":1202,"children":1203},{"style":155},[1204],{"type":26,"value":1205}," ([keyPath isEqualToString",{"type":21,"tag":138,"props":1207,"children":1208},{"style":161},[1209],{"type":26,"value":202},{"type":21,"tag":138,"props":1211,"children":1212},{"style":155},[1213],{"type":26,"value":296},{"type":21,"tag":138,"props":1215,"children":1216},{"style":299},[1217],{"type":26,"value":1218},"\"status\"",{"type":21,"tag":138,"props":1220,"children":1221},{"style":155},[1222],{"type":26,"value":1223},"])\n",{"type":21,"tag":138,"props":1225,"children":1226},{"class":140,"line":182},[1227],{"type":21,"tag":138,"props":1228,"children":1229},{"style":155},[1230],{"type":26,"value":431},{"type":21,"tag":138,"props":1232,"children":1233},{"class":140,"line":216},[1234,1238,1243,1248],{"type":21,"tag":138,"props":1235,"children":1236},{"style":161},[1237],{"type":26,"value":720},{"type":21,"tag":138,"props":1239,"children":1240},{"style":155},[1241],{"type":26,"value":1242}," (AVPlayerItemStatusReadyToPlay ",{"type":21,"tag":138,"props":1244,"children":1245},{"style":161},[1246],{"type":26,"value":1247},"==",{"type":21,"tag":138,"props":1249,"children":1250},{"style":155},[1251],{"type":26,"value":1252}," _player.currentItem.status)\n",{"type":21,"tag":138,"props":1254,"children":1255},{"class":140,"line":245},[1256],{"type":21,"tag":138,"props":1257,"children":1258},{"style":155},[1259],{"type":26,"value":734},{"type":21,"tag":138,"props":1261,"children":1262},{"class":140,"line":253},[1263],{"type":21,"tag":138,"props":1264,"children":1265},{"style":155},[1266],{"type":26,"value":1267},"         [_player play];\n",{"type":21,"tag":138,"props":1269,"children":1270},{"class":140,"line":262},[1271],{"type":21,"tag":138,"props":1272,"children":1273},{"style":155},[1274],{"type":26,"value":767},{"type":21,"tag":138,"props":1276,"children":1277},{"class":140,"line":347},[1278],{"type":21,"tag":138,"props":1279,"children":1280},{"style":155},[1281],{"type":26,"value":897},{"type":21,"tag":138,"props":1283,"children":1284},{"class":140,"line":384},[1285],{"type":21,"tag":138,"props":1286,"children":1287},{"style":155},[1288],{"type":26,"value":1289},"}\n",{"type":21,"tag":22,"props":1291,"children":1292},{},[1293],{"type":26,"value":1294},"This code is pretty straightforward. If our AVPlayerItem is ready to play, then go ahead and start playing the audio composition that we created above.",{"type":21,"tag":22,"props":1296,"children":1297},{},[1298],{"type":21,"tag":75,"props":1299,"children":1300},{},[1301],{"type":26,"value":1302},"Slider Action",{"type":21,"tag":127,"props":1304,"children":1306},{"className":129,"code":1305,"language":131,"meta":8,"style":8},"// Action for our 4 sliders\n- (IBAction)mix:(id)sender\n{\n   UISlider* slider = (UISlider*)sender;\n\n   [self setVolume:slider.value\n          forTrack:[NSString stringWithFormat:@\"track%d\", slider.tag]];\n   [self applyAudioMix];\n}\n",[1307],{"type":21,"tag":134,"props":1308,"children":1309},{"__ignoreMap":8},[1310,1318,1339,1346,1381,1388,1418,1453,1469],{"type":21,"tag":138,"props":1311,"children":1312},{"class":140,"line":141},[1313],{"type":21,"tag":138,"props":1314,"children":1315},{"style":145},[1316],{"type":26,"value":1317},"// Action for our 4 sliders\n",{"type":21,"tag":138,"props":1319,"children":1320},{"class":140,"line":151},[1321,1325,1330,1334],{"type":21,"tag":138,"props":1322,"children":1323},{"style":161},[1324],{"type":26,"value":1116},{"type":21,"tag":138,"props":1326,"children":1327},{"style":155},[1328],{"type":26,"value":1329}," (IBAction)mix",{"type":21,"tag":138,"props":1331,"children":1332},{"style":161},[1333],{"type":26,"value":202},{"type":21,"tag":138,"props":1335,"children":1336},{"style":155},[1337],{"type":26,"value":1338},"(id)sender\n",{"type":21,"tag":138,"props":1340,"children":1341},{"class":140,"line":172},[1342],{"type":21,"tag":138,"props":1343,"children":1344},{"style":155},[1345],{"type":26,"value":1192},{"type":21,"tag":138,"props":1347,"children":1348},{"class":140,"line":182},[1349,1354,1358,1363,1367,1372,1376],{"type":21,"tag":138,"props":1350,"children":1351},{"style":155},[1352],{"type":26,"value":1353},"   UISlider",{"type":21,"tag":138,"props":1355,"children":1356},{"style":161},[1357],{"type":26,"value":273},{"type":21,"tag":138,"props":1359,"children":1360},{"style":155},[1361],{"type":26,"value":1362}," slider ",{"type":21,"tag":138,"props":1364,"children":1365},{"style":161},[1366],{"type":26,"value":164},{"type":21,"tag":138,"props":1368,"children":1369},{"style":155},[1370],{"type":26,"value":1371}," (UISlider",{"type":21,"tag":138,"props":1373,"children":1374},{"style":161},[1375],{"type":26,"value":273},{"type":21,"tag":138,"props":1377,"children":1378},{"style":155},[1379],{"type":26,"value":1380},")sender;\n",{"type":21,"tag":138,"props":1382,"children":1383},{"class":140,"line":216},[1384],{"type":21,"tag":138,"props":1385,"children":1386},{"emptyLinePlaceholder":176},[1387],{"type":26,"value":179},{"type":21,"tag":138,"props":1389,"children":1390},{"class":140,"line":245},[1391,1396,1400,1404,1408,1413],{"type":21,"tag":138,"props":1392,"children":1393},{"style":155},[1394],{"type":26,"value":1395},"   [",{"type":21,"tag":138,"props":1397,"children":1398},{"style":205},[1399],{"type":26,"value":860},{"type":21,"tag":138,"props":1401,"children":1402},{"style":155},[1403],{"type":26,"value":865},{"type":21,"tag":138,"props":1405,"children":1406},{"style":161},[1407],{"type":26,"value":202},{"type":21,"tag":138,"props":1409,"children":1410},{"style":155},[1411],{"type":26,"value":1412},"slider.",{"type":21,"tag":138,"props":1414,"children":1415},{"style":205},[1416],{"type":26,"value":1417},"value\n",{"type":21,"tag":138,"props":1419,"children":1420},{"class":140,"line":253},[1421,1426,1430,1435,1439,1443,1448],{"type":21,"tag":138,"props":1422,"children":1423},{"style":155},[1424],{"type":26,"value":1425},"          forTrack",{"type":21,"tag":138,"props":1427,"children":1428},{"style":161},[1429],{"type":26,"value":202},{"type":21,"tag":138,"props":1431,"children":1432},{"style":155},[1433],{"type":26,"value":1434},"[NSString stringWithFormat",{"type":21,"tag":138,"props":1436,"children":1437},{"style":161},[1438],{"type":26,"value":202},{"type":21,"tag":138,"props":1440,"children":1441},{"style":155},[1442],{"type":26,"value":296},{"type":21,"tag":138,"props":1444,"children":1445},{"style":299},[1446],{"type":26,"value":1447},"\"track%d\"",{"type":21,"tag":138,"props":1449,"children":1450},{"style":155},[1451],{"type":26,"value":1452},", slider.tag]];\n",{"type":21,"tag":138,"props":1454,"children":1455},{"class":140,"line":262},[1456,1460,1464],{"type":21,"tag":138,"props":1457,"children":1458},{"style":155},[1459],{"type":26,"value":1395},{"type":21,"tag":138,"props":1461,"children":1462},{"style":205},[1463],{"type":26,"value":860},{"type":21,"tag":138,"props":1465,"children":1466},{"style":155},[1467],{"type":26,"value":1468}," applyAudioMix];\n",{"type":21,"tag":138,"props":1470,"children":1471},{"class":140,"line":347},[1472],{"type":21,"tag":138,"props":1473,"children":1474},{"style":155},[1475],{"type":26,"value":1289},{"type":21,"tag":22,"props":1477,"children":1478},{},[1479],{"type":26,"value":1480},"Our UI has four UISliders, each of which call this action method. The sliders are tagged from 1 to 4 and we use the tag to map to the corresponding audio track. The value of the slider is configured to be between 0.0 and 1.0 so we use it to set the track volume and then apply the updated audio mix to the composition.",{"type":21,"tag":22,"props":1482,"children":1483},{},[1484],{"type":21,"tag":75,"props":1485,"children":1486},{},[1487],{"type":26,"value":1488},"Setting the Volume",{"type":21,"tag":127,"props":1490,"children":1492},{"className":129,"code":1491,"language":131,"meta":8,"style":8},"// Set the volumne (0.0 - 1.0) for the given track\n- (void)setVolume:(float)volume forTrack:(NSString*)audioTrackName\n{\n   [_audioMixValues setValue:[NSNumber numberWithFloat:volume] forKey:audioTrackName];\n}\n",[1493],{"type":21,"tag":134,"props":1494,"children":1495},{"__ignoreMap":8},[1496,1504,1543,1550,1585],{"type":21,"tag":138,"props":1497,"children":1498},{"class":140,"line":141},[1499],{"type":21,"tag":138,"props":1500,"children":1501},{"style":145},[1502],{"type":26,"value":1503},"// Set the volumne (0.0 - 1.0) for the given track\n",{"type":21,"tag":138,"props":1505,"children":1506},{"class":140,"line":151},[1507,1511,1516,1520,1525,1529,1534,1538],{"type":21,"tag":138,"props":1508,"children":1509},{"style":161},[1510],{"type":26,"value":1116},{"type":21,"tag":138,"props":1512,"children":1513},{"style":155},[1514],{"type":26,"value":1515}," (void)setVolume",{"type":21,"tag":138,"props":1517,"children":1518},{"style":161},[1519],{"type":26,"value":202},{"type":21,"tag":138,"props":1521,"children":1522},{"style":155},[1523],{"type":26,"value":1524},"(float)volume forTrack",{"type":21,"tag":138,"props":1526,"children":1527},{"style":161},[1528],{"type":26,"value":202},{"type":21,"tag":138,"props":1530,"children":1531},{"style":155},[1532],{"type":26,"value":1533},"(NSString",{"type":21,"tag":138,"props":1535,"children":1536},{"style":161},[1537],{"type":26,"value":273},{"type":21,"tag":138,"props":1539,"children":1540},{"style":155},[1541],{"type":26,"value":1542},")audioTrackName\n",{"type":21,"tag":138,"props":1544,"children":1545},{"class":140,"line":172},[1546],{"type":21,"tag":138,"props":1547,"children":1548},{"style":155},[1549],{"type":26,"value":1192},{"type":21,"tag":138,"props":1551,"children":1552},{"class":140,"line":182},[1553,1558,1562,1567,1571,1576,1580],{"type":21,"tag":138,"props":1554,"children":1555},{"style":155},[1556],{"type":26,"value":1557},"   [_audioMixValues setValue",{"type":21,"tag":138,"props":1559,"children":1560},{"style":161},[1561],{"type":26,"value":202},{"type":21,"tag":138,"props":1563,"children":1564},{"style":155},[1565],{"type":26,"value":1566},"[NSNumber numberWithFloat",{"type":21,"tag":138,"props":1568,"children":1569},{"style":161},[1570],{"type":26,"value":202},{"type":21,"tag":138,"props":1572,"children":1573},{"style":155},[1574],{"type":26,"value":1575},"volume] forKey",{"type":21,"tag":138,"props":1577,"children":1578},{"style":161},[1579],{"type":26,"value":202},{"type":21,"tag":138,"props":1581,"children":1582},{"style":155},[1583],{"type":26,"value":1584},"audioTrackName];\n",{"type":21,"tag":138,"props":1586,"children":1587},{"class":140,"line":216},[1588],{"type":21,"tag":138,"props":1589,"children":1590},{"style":155},[1591],{"type":26,"value":1289},{"type":21,"tag":22,"props":1593,"children":1594},{},[1595],{"type":26,"value":1596},"When we set the volume we simply update the value in our NSMutableDictionary that stores the volume level for each track.",{"type":21,"tag":22,"props":1598,"children":1599},{},[1600],{"type":21,"tag":75,"props":1601,"children":1602},{},[1603],{"type":26,"value":1604},"Applying the Mix",{"type":21,"tag":127,"props":1606,"children":1608},{"className":129,"code":1607,"language":131,"meta":8,"style":8},"// Build and apply an audio mix using our volume values\n- (void)applyAudioMix\n{\n   AVMutableAudioMix* mix = [AVMutableAudioMix audioMix];\n\n   NSMutableArray* inputParameters = [[NSMutableArray alloc] initWithCapacity:0];\n\n   [_audioMixTrackIDs enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL*stop) {\n      AVAssetTrack* track = [self trackWithId:(CMPersistentTrackID)[(NSNumber*)obj integerValue]];\n\n      AVMutableAudioMixInputParameters* params = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];\n\n      [params setVolume:[[_audioMixValues valueForKey:key] floatValue]\n                 atTime:kCMTimeZero];\n\n      [inputParameters addObject:params];\n   }];\n\n   mix.inputParameters = inputParameters;\n\n   _player.currentItem.audioMix = mix;\n}\n",[1609],{"type":21,"tag":134,"props":1610,"children":1611},{"__ignoreMap":8},[1612,1620,1632,1639,1665,1672,1710,1717,1744,1797,1804,1839,1846,1872,1889,1896,1913,1921,1928,1945,1952,1969],{"type":21,"tag":138,"props":1613,"children":1614},{"class":140,"line":141},[1615],{"type":21,"tag":138,"props":1616,"children":1617},{"style":145},[1618],{"type":26,"value":1619},"// Build and apply an audio mix using our volume values\n",{"type":21,"tag":138,"props":1621,"children":1622},{"class":140,"line":151},[1623,1627],{"type":21,"tag":138,"props":1624,"children":1625},{"style":161},[1626],{"type":26,"value":1116},{"type":21,"tag":138,"props":1628,"children":1629},{"style":155},[1630],{"type":26,"value":1631}," (void)applyAudioMix\n",{"type":21,"tag":138,"props":1633,"children":1634},{"class":140,"line":172},[1635],{"type":21,"tag":138,"props":1636,"children":1637},{"style":155},[1638],{"type":26,"value":1192},{"type":21,"tag":138,"props":1640,"children":1641},{"class":140,"line":182},[1642,1647,1651,1656,1660],{"type":21,"tag":138,"props":1643,"children":1644},{"style":155},[1645],{"type":26,"value":1646},"   AVMutableAudioMix",{"type":21,"tag":138,"props":1648,"children":1649},{"style":161},[1650],{"type":26,"value":273},{"type":21,"tag":138,"props":1652,"children":1653},{"style":155},[1654],{"type":26,"value":1655}," mix ",{"type":21,"tag":138,"props":1657,"children":1658},{"style":161},[1659],{"type":26,"value":164},{"type":21,"tag":138,"props":1661,"children":1662},{"style":155},[1663],{"type":26,"value":1664}," [AVMutableAudioMix audioMix];\n",{"type":21,"tag":138,"props":1666,"children":1667},{"class":140,"line":216},[1668],{"type":21,"tag":138,"props":1669,"children":1670},{"emptyLinePlaceholder":176},[1671],{"type":26,"value":179},{"type":21,"tag":138,"props":1673,"children":1674},{"class":140,"line":245},[1675,1680,1684,1689,1693,1698,1702,1706],{"type":21,"tag":138,"props":1676,"children":1677},{"style":155},[1678],{"type":26,"value":1679},"   NSMutableArray",{"type":21,"tag":138,"props":1681,"children":1682},{"style":161},[1683],{"type":26,"value":273},{"type":21,"tag":138,"props":1685,"children":1686},{"style":155},[1687],{"type":26,"value":1688}," inputParameters ",{"type":21,"tag":138,"props":1690,"children":1691},{"style":161},[1692],{"type":26,"value":164},{"type":21,"tag":138,"props":1694,"children":1695},{"style":155},[1696],{"type":26,"value":1697}," [[NSMutableArray alloc] initWithCapacity",{"type":21,"tag":138,"props":1699,"children":1700},{"style":161},[1701],{"type":26,"value":202},{"type":21,"tag":138,"props":1703,"children":1704},{"style":205},[1705],{"type":26,"value":208},{"type":21,"tag":138,"props":1707,"children":1708},{"style":155},[1709],{"type":26,"value":213},{"type":21,"tag":138,"props":1711,"children":1712},{"class":140,"line":253},[1713],{"type":21,"tag":138,"props":1714,"children":1715},{"emptyLinePlaceholder":176},[1716],{"type":26,"value":179},{"type":21,"tag":138,"props":1718,"children":1719},{"class":140,"line":262},[1720,1725,1730,1735,1739],{"type":21,"tag":138,"props":1721,"children":1722},{"style":155},[1723],{"type":26,"value":1724},"   [_audioMixTrackIDs enumerateKeysAndObjectsUsingBlock",{"type":21,"tag":138,"props":1726,"children":1727},{"style":161},[1728],{"type":26,"value":1729},":^",{"type":21,"tag":138,"props":1731,"children":1732},{"style":155},[1733],{"type":26,"value":1734},"(id key, id obj, BOOL",{"type":21,"tag":138,"props":1736,"children":1737},{"style":161},[1738],{"type":26,"value":273},{"type":21,"tag":138,"props":1740,"children":1741},{"style":155},[1742],{"type":26,"value":1743},"stop) {\n",{"type":21,"tag":138,"props":1745,"children":1746},{"class":140,"line":347},[1747,1752,1756,1761,1765,1770,1774,1779,1783,1788,1792],{"type":21,"tag":138,"props":1748,"children":1749},{"style":155},[1750],{"type":26,"value":1751},"      AVAssetTrack",{"type":21,"tag":138,"props":1753,"children":1754},{"style":161},[1755],{"type":26,"value":273},{"type":21,"tag":138,"props":1757,"children":1758},{"style":155},[1759],{"type":26,"value":1760}," track ",{"type":21,"tag":138,"props":1762,"children":1763},{"style":161},[1764],{"type":26,"value":164},{"type":21,"tag":138,"props":1766,"children":1767},{"style":155},[1768],{"type":26,"value":1769}," [",{"type":21,"tag":138,"props":1771,"children":1772},{"style":205},[1773],{"type":26,"value":860},{"type":21,"tag":138,"props":1775,"children":1776},{"style":155},[1777],{"type":26,"value":1778}," trackWithId",{"type":21,"tag":138,"props":1780,"children":1781},{"style":161},[1782],{"type":26,"value":202},{"type":21,"tag":138,"props":1784,"children":1785},{"style":155},[1786],{"type":26,"value":1787},"(CMPersistentTrackID)[(NSNumber",{"type":21,"tag":138,"props":1789,"children":1790},{"style":161},[1791],{"type":26,"value":273},{"type":21,"tag":138,"props":1793,"children":1794},{"style":155},[1795],{"type":26,"value":1796},")obj integerValue]];\n",{"type":21,"tag":138,"props":1798,"children":1799},{"class":140,"line":384},[1800],{"type":21,"tag":138,"props":1801,"children":1802},{"emptyLinePlaceholder":176},[1803],{"type":26,"value":179},{"type":21,"tag":138,"props":1805,"children":1806},{"class":140,"line":392},[1807,1812,1816,1821,1825,1830,1834],{"type":21,"tag":138,"props":1808,"children":1809},{"style":155},[1810],{"type":26,"value":1811},"      AVMutableAudioMixInputParameters",{"type":21,"tag":138,"props":1813,"children":1814},{"style":161},[1815],{"type":26,"value":273},{"type":21,"tag":138,"props":1817,"children":1818},{"style":155},[1819],{"type":26,"value":1820}," params ",{"type":21,"tag":138,"props":1822,"children":1823},{"style":161},[1824],{"type":26,"value":164},{"type":21,"tag":138,"props":1826,"children":1827},{"style":155},[1828],{"type":26,"value":1829}," [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack",{"type":21,"tag":138,"props":1831,"children":1832},{"style":161},[1833],{"type":26,"value":202},{"type":21,"tag":138,"props":1835,"children":1836},{"style":155},[1837],{"type":26,"value":1838},"track];\n",{"type":21,"tag":138,"props":1840,"children":1841},{"class":140,"line":425},[1842],{"type":21,"tag":138,"props":1843,"children":1844},{"emptyLinePlaceholder":176},[1845],{"type":26,"value":179},{"type":21,"tag":138,"props":1847,"children":1848},{"class":140,"line":434},[1849,1854,1858,1863,1867],{"type":21,"tag":138,"props":1850,"children":1851},{"style":155},[1852],{"type":26,"value":1853},"      [params setVolume",{"type":21,"tag":138,"props":1855,"children":1856},{"style":161},[1857],{"type":26,"value":202},{"type":21,"tag":138,"props":1859,"children":1860},{"style":155},[1861],{"type":26,"value":1862},"[[_audioMixValues valueForKey",{"type":21,"tag":138,"props":1864,"children":1865},{"style":161},[1866],{"type":26,"value":202},{"type":21,"tag":138,"props":1868,"children":1869},{"style":155},[1870],{"type":26,"value":1871},"key] floatValue]\n",{"type":21,"tag":138,"props":1873,"children":1874},{"class":140,"line":497},[1875,1880,1884],{"type":21,"tag":138,"props":1876,"children":1877},{"style":155},[1878],{"type":26,"value":1879},"                 atTime",{"type":21,"tag":138,"props":1881,"children":1882},{"style":161},[1883],{"type":26,"value":202},{"type":21,"tag":138,"props":1885,"children":1886},{"style":155},[1887],{"type":26,"value":1888},"kCMTimeZero];\n",{"type":21,"tag":138,"props":1890,"children":1891},{"class":140,"line":518},[1892],{"type":21,"tag":138,"props":1893,"children":1894},{"emptyLinePlaceholder":176},[1895],{"type":26,"value":179},{"type":21,"tag":138,"props":1897,"children":1898},{"class":140,"line":526},[1899,1904,1908],{"type":21,"tag":138,"props":1900,"children":1901},{"style":155},[1902],{"type":26,"value":1903},"      [inputParameters addObject",{"type":21,"tag":138,"props":1905,"children":1906},{"style":161},[1907],{"type":26,"value":202},{"type":21,"tag":138,"props":1909,"children":1910},{"style":155},[1911],{"type":26,"value":1912},"params];\n",{"type":21,"tag":138,"props":1914,"children":1915},{"class":140,"line":562},[1916],{"type":21,"tag":138,"props":1917,"children":1918},{"style":155},[1919],{"type":26,"value":1920},"   }];\n",{"type":21,"tag":138,"props":1922,"children":1923},{"class":140,"line":580},[1924],{"type":21,"tag":138,"props":1925,"children":1926},{"emptyLinePlaceholder":176},[1927],{"type":26,"value":179},{"type":21,"tag":138,"props":1929,"children":1930},{"class":140,"line":588},[1931,1936,1940],{"type":21,"tag":138,"props":1932,"children":1933},{"style":155},[1934],{"type":26,"value":1935},"   mix.inputParameters ",{"type":21,"tag":138,"props":1937,"children":1938},{"style":161},[1939],{"type":26,"value":164},{"type":21,"tag":138,"props":1941,"children":1942},{"style":155},[1943],{"type":26,"value":1944}," inputParameters;\n",{"type":21,"tag":138,"props":1946,"children":1947},{"class":140,"line":606},[1948],{"type":21,"tag":138,"props":1949,"children":1950},{"emptyLinePlaceholder":176},[1951],{"type":26,"value":179},{"type":21,"tag":138,"props":1953,"children":1954},{"class":140,"line":629},[1955,1960,1964],{"type":21,"tag":138,"props":1956,"children":1957},{"style":155},[1958],{"type":26,"value":1959},"   _player.currentItem.audioMix ",{"type":21,"tag":138,"props":1961,"children":1962},{"style":161},[1963],{"type":26,"value":164},{"type":21,"tag":138,"props":1965,"children":1966},{"style":155},[1967],{"type":26,"value":1968}," mix;\n",{"type":21,"tag":138,"props":1970,"children":1971},{"class":140,"line":669},[1972],{"type":21,"tag":138,"props":1973,"children":1974},{"style":155},[1975],{"type":26,"value":1289},{"type":21,"tag":22,"props":1977,"children":1978},{},[1979,1981,1988,1990,1997],{"type":26,"value":1980},"Here's where we update and apply the audio mix to our composition. First we create an instance of the ",{"type":21,"tag":29,"props":1982,"children":1985},{"href":1983,"rel":1984},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableAudioMix_Class/Reference/Reference.html",[33],[1986],{"type":26,"value":1987},"AVMutableAudioMix",{"type":26,"value":1989}," class and then for each track create an ",{"type":21,"tag":29,"props":1991,"children":1994},{"href":1992,"rel":1993},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableAudioMixInputParameters_Class/Reference/Reference.html",[33],[1995],{"type":26,"value":1996},"AVMutableAudioMixInputParameters",{"type":26,"value":1998}," instance for the track with the track volume as determined by the current slider value that we've stored. We add the AVMutableAudioMixInputParameters to an array and then set the parameters for our AVMutableAudioMix instance. Finally, we set the mix for the current item of our AVPlayer to our newly created mix.",{"type":21,"tag":22,"props":2000,"children":2001},{},[2002],{"type":21,"tag":75,"props":2003,"children":2004},{},[2005],{"type":26,"value":2006},"Closing Thoughts",{"type":21,"tag":22,"props":2008,"children":2009},{},[2010],{"type":26,"value":2011},"In just a few methods we have a simple four track mixer. This would have been much harder to accomplish without AVFoundation since we'd likely need to use the low-level Core Audio APIs.",{"type":21,"tag":22,"props":2013,"children":2014},{},[2015],{"type":26,"value":2016},"It will be interesting to see what updates Apple has planned for AVFoundation in iOS 6.0 and OS X 10.8 and if the related QuickTime APIs in OS X will be deprecated in favor of AVFoundation.",{"type":21,"tag":2018,"props":2019,"children":2020},"style",{},[2021],{"type":26,"value":2022},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":172,"depth":172,"links":2024},[],"markdown","content:shuey:2012-07:mixer.md","content","shuey/2012-07/mixer.md","shuey/2012-07/mixer","md",{"user":2032,"name":2033},"shuey","Steven Huey",1780330273092]