[{"data":1,"prerenderedAt":2853},["ShallowReactive",2],{"article_list_apple_":3},[4,271,551,731,2741,2799],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"tags":11,"excerpt":10,"image":16,"publishDate":17,"body":18,"_type":262,"_id":263,"_source":264,"_file":265,"_stem":266,"_extension":267,"author":268},"/jbagley/2023-06-01/universal_ffmpeg_custom_builds","2023-06-01",false,"","Building Universal FFmpeg Custom Binaries","I am using a very pared down set of FFMpeg features for a macOS project that I\nbuild into a custom library. I had a script set up to configure the build which\nworked fine on my Intel based MacBook Pro. Then I upgraded to an Apple Silicon\nMacBookPro and wanted to run natively, or at least see what happened when I\ndid. To build, FFMpeg uses autoconf which produces a makefile that then handles\nthe build.",[12,13,14,15],"c","bash","ffmpeg","apple","/jbagley/2023-06-01/img/header.png","2024-04-01",{"type":19,"children":20,"toc":254},"root",[21,30,35,41,74,87,93,98,103,114,119,156,177,183,203,212,224,236,249],{"type":22,"tag":23,"props":24,"children":26},"element","h2",{"id":25},"motivation",[27],{"type":28,"value":29},"text","Motivation",{"type":22,"tag":31,"props":32,"children":33},"p",{},[34],{"type":28,"value":10},{"type":22,"tag":23,"props":36,"children":38},{"id":37},"the-simplest-thing-which-could-work-but-didnt",[39],{"type":28,"value":40},"The simplest thing which could work but didn't",{"type":22,"tag":31,"props":42,"children":43},{},[44,46,53,55,61,63,72],{"type":28,"value":45},"Autoconf supports passing flags for the compiler in the call to configure. I was\nalready passing ",{"type":22,"tag":47,"props":48,"children":50},"code",{"className":49},[],[51],{"type":28,"value":52},"-arch x86_64",{"type":28,"value":54}," as part of ",{"type":22,"tag":47,"props":56,"children":58},{"className":57},[],[59],{"type":28,"value":60},"--extra-cflags",{"type":28,"value":62},". Its\n",{"type":22,"tag":64,"props":65,"children":69},"a",{"href":66,"rel":67},"https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Multiple-Architectures.html",[68],"nofollow",[70],{"type":28,"value":71},"documentation",{"type":28,"value":73},"\nsays that I may provide more than one architecture on macOS. That page notes\nthat this doesn't always work.",{"type":22,"tag":31,"props":75,"children":76},{},[77,79,85],{"type":28,"value":78},"Based on that, I tried ",{"type":22,"tag":47,"props":80,"children":82},{"className":81},[],[83],{"type":28,"value":84},"-arch x86_64 -arch arm64",{"type":28,"value":86},"', and as foreshadowed it\nindeed did not work. Autoconf's compiler tests would fail when trying the x86_64\nbuild with clang. I went through some more permutations of arguments, but in the\nend I had to do separate builds for each architecture.",{"type":22,"tag":23,"props":88,"children":90},{"id":89},"building",[91],{"type":28,"value":92},"Building",{"type":22,"tag":31,"props":94,"children":95},{},[96],{"type":28,"value":97},"I use a build directory rather than calling configure in the top of my FFmpeg\nworking copy and dirtying it up. I am running this from that build dir.",{"type":22,"tag":31,"props":99,"children":100},{},[101],{"type":28,"value":102},"Here is bash psuedocode of my build script:",{"type":22,"tag":104,"props":105,"children":109},"pre",{"className":106,"code":108,"language":28},[107],"language-text","for arch in x86_64 arm64; do\n\n   rm -rf Makefile config.h ffbuild lib* tests \n\n    ../configure --cc=clang \\\n                 --extra-cflags=\"-arch $arch\" \\\n                 --extra-ldflags=\"-arch $arch\"  \\\n                 --build_suffix=\"$install_dir\"  \\\n                 --prefix=\"path/to/where/I/want/the/libs/to/be/copied/by/make/install\" \\\n                 # other flags for ffmpeg configuration, see '../configure -h' output\n    make -j\n    make install\ndone\n",[110],{"type":22,"tag":47,"props":111,"children":112},{"__ignoreMap":8},[113],{"type":28,"value":108},{"type":22,"tag":31,"props":115,"children":116},{},[117],{"type":28,"value":118},"Looping through the desired architectures, first it cleans the build directory\nto get rid of the previous architecture output, then configures, building and\ninstalling the library.",{"type":22,"tag":31,"props":120,"children":121},{},[122,124,130,132,138,140,146,148,154],{"type":28,"value":123},"In the end, you have two sets of library files installed into the path passed\nwith ",{"type":22,"tag":47,"props":125,"children":127},{"className":126},[],[128],{"type":28,"value":129},"--prefix",{"type":28,"value":131}," with the suffixes ",{"type":22,"tag":47,"props":133,"children":135},{"className":134},[],[136],{"type":28,"value":137},"_x86-64",{"type":28,"value":139}," and ",{"type":22,"tag":47,"props":141,"children":143},{"className":142},[],[144],{"type":28,"value":145},"_arm64",{"type":28,"value":147}," provided by the\n",{"type":22,"tag":47,"props":149,"children":151},{"className":150},[],[152],{"type":28,"value":153},"--build_suffix",{"type":28,"value":155}," argument.",{"type":22,"tag":31,"props":157,"children":158},{},[159,161,167,169,175],{"type":28,"value":160},"I needed to pass the architecture again with ",{"type":22,"tag":47,"props":162,"children":164},{"className":163},[],[165],{"type":28,"value":166},"--extra-ldflags",{"type":28,"value":168}," to avoid the\nautoconf compiler test failing. The most basic test for compiler support would\nfail when an x86_64 ",{"type":22,"tag":47,"props":170,"children":172},{"className":171},[],[173],{"type":28,"value":174},".o",{"type":28,"value":176}," file couldn't be linked to an arm64 exectuable.",{"type":22,"tag":23,"props":178,"children":180},{"id":179},"linking-the-universal-libraries",[181],{"type":28,"value":182},"Linking The Universal Libraries",{"type":22,"tag":31,"props":184,"children":185},{},[186,188,194,196,201],{"type":28,"value":187},"The call to ",{"type":22,"tag":47,"props":189,"children":191},{"className":190},[],[192],{"type":28,"value":193},"lipo",{"type":28,"value":195}," turned out to be simple. The trickier part for me was\nbuilding the array of names to pass to ",{"type":22,"tag":47,"props":197,"children":199},{"className":198},[],[200],{"type":28,"value":193},{"type":28,"value":202}," as input files. I don't remember\nthe last time I used these.",{"type":22,"tag":104,"props":204,"children":207},{"className":205,"code":206,"language":28},[107],"lib_output_dir=\u003Cthe same path I used as the --prefix argument to configure above>\ncd \"$lib_output_dir\"\nfor lib_name in \u003Clib names I produced in my build without the file extension, e.g. libavcodec>; do\n    input_names=()\n    for arch in x86_64 arm64; do\n        input_names+=(${lib_name}_{$arch}.a)\n    done\n    /usr/bin/lipo -create -output ${lib_name}.a ${input_names[*]}\n    rm ${input_names}[*]}\ndone\ncd -\n",[208],{"type":22,"tag":47,"props":209,"children":210},{"__ignoreMap":8},[211],{"type":28,"value":206},{"type":22,"tag":31,"props":213,"children":214},{},[215,217,222],{"type":28,"value":216},"It changes to the directory where the first section installed the libraries. Of\ncourse, ",{"type":22,"tag":47,"props":218,"children":220},{"className":219},[],[221],{"type":28,"value":193},{"type":28,"value":223}," could be run on the libs within the build folder, but my script\nwas already installing them, and I found this more convenient and simple.",{"type":22,"tag":31,"props":225,"children":226},{},[227,229,234],{"type":28,"value":228},"For each architecture, it builds the array of library filenames, including the\narchitecture suffix of each. That array gives the typical DRY advantages and\nkeeps the invocation of ",{"type":22,"tag":47,"props":230,"children":232},{"className":231},[],[233],{"type":28,"value":193},{"type":28,"value":235}," simple.",{"type":22,"tag":31,"props":237,"children":238},{},[239,241,247],{"type":28,"value":240},"You can confirm it worked using the ",{"type":22,"tag":47,"props":242,"children":244},{"className":243},[],[245],{"type":28,"value":246},"file",{"type":28,"value":248}," utility. You should see a line for each\narchitecture it its output.",{"type":22,"tag":31,"props":250,"children":251},{},[252],{"type":28,"value":253},"That's it. If you have a better way, or see something I can do better here, let\nme know.",{"title":8,"searchDepth":255,"depth":255,"links":256},3,[257,259,260,261],{"id":25,"depth":258,"text":29},2,{"id":37,"depth":258,"text":40},{"id":89,"depth":258,"text":92},{"id":179,"depth":258,"text":182},"markdown","content:jbagley:2023-06-01:Universal_FFMPEG_custom_builds.md","content","jbagley/2023-06-01/Universal_FFMPEG_custom_builds.md","jbagley/2023-06-01/Universal_FFMPEG_custom_builds","md",{"user":269,"name":270},"jbagley","Jason Bagley",{"_path":272,"_dir":273,"_draft":7,"_partial":7,"_locale":8,"title":274,"description":275,"excerpt":275,"image":276,"publishDate":277,"tags":278,"body":282,"_type":262,"_id":545,"_source":264,"_file":546,"_stem":547,"_extension":267,"author":548},"/asherbrooke/2020-4/watchwah","2020-4","Bringing an Idea to Life: WatchWah Proof of Concept","\"Wouldn't it be cool if...\"","/asherbrooke/2020-4/img/Guitar_and_Watch.jpeg","2020-04-01",[279,15,280,281],"ios","watch","juce",{"type":19,"children":283,"toc":536},[284,292,297,303,308,313,342,347,353,358,363,368,375,389,401,406,412,417,423,428,442,447,452,457,462,467,473,487,492,506,528],{"type":22,"tag":31,"props":285,"children":286},{},[287],{"type":22,"tag":288,"props":289,"children":290},"em",{},[291],{"type":28,"value":275},{"type":22,"tag":31,"props":293,"children":294},{},[295],{"type":28,"value":296},"We've all had that thought about something. How do you get from there to a product you can use and share with others? When I found myself playing with an idea that seemed exciting and new, I decided to capture some notes on the process, from the perspective of an Engineering Manager at a company that's all about implementing people's creative visions.",{"type":22,"tag":23,"props":298,"children":300},{"id":299},"the-idea",[301],{"type":28,"value":302},"The Idea",{"type":22,"tag":31,"props":304,"children":305},{},[306],{"type":28,"value":307},"In addition to working as Art+Logic's Director of Engineering I've been a performing musician for much of my life. A year ago I bought an Apple Watch and it occurred to me that this small computer, packed with sensors monitoring all sorts of interesting things, could be used to enhance some element of musical expression.",{"type":22,"tag":31,"props":309,"children":310},{},[311],{"type":28,"value":312},"As a professional software developer I've learned that a good idea includes these qualities:",{"type":22,"tag":314,"props":315,"children":316},"ul",{},[317,323,328],{"type":22,"tag":318,"props":319,"children":320},"li",{},[321],{"type":28,"value":322},"It needs to spark your passion, or at least get you curious. If it's something you're personally neutral about, but think might make you money, it's much harder to stay with it over the long haul. My idea was fairly simple, and I felt curious enough to spend some time on it.",{"type":22,"tag":318,"props":324,"children":325},{},[326],{"type":28,"value":327},"It's framed generally enough to be resilient as challenges arise. I've seen clients cling to specific details of their projects, at the expense of the product, when a looser conception of their goals might have allowed them to pivot more gracefully. In my case, \"Can I use my watch to enhance my musical performance\" seemed sufficiently general.",{"type":22,"tag":318,"props":329,"children":330},{},[331,333,340],{"type":28,"value":332},"It's been researched enough to know what possible challenges or competitors exist. I found ",{"type":22,"tag":64,"props":334,"children":337},{"href":335,"rel":336},"https://www.synthanatomy.com/2019/02/midiwrist-apple-watch-midi-controller.html",[68],[338],{"type":28,"value":339},"an existing system",{"type":28,"value":341}," that allowed the user to send messages from the Apple Watch to audio applications, but it didn't use the sensors. I was pleased that there wasn't anything quite like my idea that was already available, but also wondered if it might be unexpectedly difficult to implement, since nobody seemed to have done this before.",{"type":22,"tag":31,"props":343,"children":344},{},[345],{"type":28,"value":346},"Interestingly, I'd say \"the idea is possible\" is not always an important question to ask. If it's not possible now it may be in the future, and indeed it's hard to say whether or not something can be done until you try to do it.",{"type":22,"tag":23,"props":348,"children":350},{"id":349},"development",[351],{"type":28,"value":352},"Development",{"type":22,"tag":31,"props":354,"children":355},{},[356],{"type":28,"value":357},"I love the idea of iterative development, and it's something we do a lot of at Art+Logic. With a new and unproven idea it's extremely valuable; how quickly (and cheaply) can you learn if your idea will work, and how can it be refined, step-wise, through experimentation?",{"type":22,"tag":31,"props":359,"children":360},{},[361],{"type":28,"value":362},"My idea seemed to have a few parts: getting sensor data from the watch, bringing that data to a guitar effect to control it's behavior, and then the effect itself. I had a vision of using my watch to control a physical \"stomp-box\" style guitar effects pedal, so I wouldn't need to be tethered to a computer, but to test and refine the basic, big-picture idea that seemed excessive, so I opted for something simpler.",{"type":22,"tag":31,"props":364,"children":365},{},[366],{"type":28,"value":367},"Not only is a fast proof-of-concept a more reasonable business proposition, but it can be hard to sustain the passion for an untested idea over the months it takes to build out a complete solution. Iterative development allows for a whole bunch of successes along the way, which keeps excitement and engagement high. Failures happen too, admittedly, but they're usually cheaper and less disappointing than seeing a lengthy project abandoned. Spoiler alert - there are no major failures in this article!",{"type":22,"tag":369,"props":370,"children":372},"h3",{"id":371},"the-watch",[373],{"type":28,"value":374},"The Watch",{"type":22,"tag":31,"props":376,"children":377},{},[378,380,387],{"type":28,"value":379},"A quick search turned up ",{"type":22,"tag":64,"props":381,"children":384},{"href":382,"rel":383},"http://sensorlog.berndthomas.net",[68],[385],{"type":28,"value":386},"SensorLog",{"type":28,"value":388}," for the iPhone and Apple Watch. It's an app that can write sensor data to file, or stream it via a network socket. I even approached testing out this app iteratively - I first logged my data to file to see what the sensor data looked like, so I could make a guess about which sensors might meed my needs, before investing time in reading a live stream of data.",{"type":22,"tag":31,"props":390,"children":391},{},[392,394,399],{"type":28,"value":393},"I had an initial misstep as I learned how to use the app. I was using my iPhone to log what I believed to be watch sensor data. I wiggled my wrist around to generate interesting watch information for the log, but the app was actually monitoring the sensors on the ",{"type":22,"tag":288,"props":395,"children":396},{},[397],{"type":28,"value":398},"phone",{"type":28,"value":400},"! I spent an hour trying to convince myself that I saw meaningful patterns in the accelerometer and other sensor data, when it was all being created by a device sitting motionless upon my table. After discovering my mistake and switching the system over to monitoring the watch I was delighted to find dramatically varying data that clearly correlated with my previous movements. I graphed data in a spreadsheet program from a bunch of different possible sensors, and saw lots of possibilities.",{"type":22,"tag":31,"props":402,"children":403},{},[404],{"type":28,"value":405},"Documenting the process is really valuable. When you're not completely sure what you're going for, having notes about the journey can provide additional options later on. I decided to start with accelerometer data, but added notes to a \"Future\" document, indicating that it might be worth trying the gyro sensor, or other CoreMotion data.",{"type":22,"tag":369,"props":407,"children":409},{"id":408},"the-effect",[410],{"type":28,"value":411},"The Effect",{"type":22,"tag":31,"props":413,"children":414},{},[415],{"type":28,"value":416},"It appeared that the natural movements of my wrist and body were indeed enough for the sensors to output interesting information. That had been my hope, since it meant that a player could add some nuance without having to learn a whole new approach to playing (as with a foot pedal). I decided that the first thing I would try would be controlling a wah effect. This is a movable band pass filter that adds a lot of character and expressiveness to a sound, but can also be relatively subtle and flexible as to when it's applied. In other words even a somewhat random movement of the filter might be kind of interesting. I decided to use my existing recording software (Logic Pro) to process the guitar sound. I set up a Logic project that featured Apple's Fuzz-Wah effect on my guitar channel. While my ultimate goal was to have a standalone effects processor, possibly based on an effect I would write myself, staying focused on testing the basic idea was the priority, and using Logic made this part of the test trivially easy.",{"type":22,"tag":369,"props":418,"children":420},{"id":419},"the-app",[421],{"type":28,"value":422},"The App",{"type":22,"tag":31,"props":424,"children":425},{},[426],{"type":28,"value":427},"The missing link between the watch and the wah effect was some piece of software that could listen for the incoming sensor data and convert it to a form that the wah could understand. MIDI seemed the obvious answer, since Logic has extensive capacity for remote control by MIDI, and standardized formats often provide the greatest flexibility. There was no obvious way to convert socket-based, comma-separated numbers to MIDI (aside from possibly using a fairly expensive 3rd-party product like Max/MSP), so I decided it was time to write some code.",{"type":22,"tag":31,"props":429,"children":430},{},[431,433,440],{"type":28,"value":432},"I've come to really appreciate the ",{"type":22,"tag":64,"props":434,"children":437},{"href":435,"rel":436},"https://juce.com/",[68],[438],{"type":28,"value":439},"JUCE C++ cross-platform development framework",{"type":28,"value":441},", particularly for audio and MIDI work. I consulted a colleague to learn what I might encounter as I set out to write my JUCE MIDI app. I was grateful for the support; it turns out that it's trivially easy to write a \"virtual MIDI port\" app with JUCE on macOS X, and extremely difficult on Windows. Knowing that in advance was great, as it confirmed my initial decision to work on macOS X. And again, as this was a proof-of-concept rather than a commercial product, one platform would be enough for now.",{"type":22,"tag":31,"props":443,"children":444},{},[445],{"type":28,"value":446},"I started with a skeleton MIDI / audio app, adding a slider to send MIDI Continuous Controller messages through a virtual MIDI port, so I could test the app without needing the watch. Within about an hour I was able to open my Logic project, launch my new app, and control the wah effect's \"pedal position\" parameter with the slider in my app.",{"type":22,"tag":31,"props":448,"children":449},{},[450],{"type":28,"value":451},"Adding JUCE's StreamingSocket class allowed me to monitor the port to which the watch would be sending data, wait for a connection, and start reading in values. This happens in a separate thread, and getting the thread performance to acceptable levels took a little fiddling.",{"type":22,"tag":31,"props":453,"children":454},{},[455],{"type":28,"value":456},"The most labor intensive portion came next; parsing the incoming sensor data and converting it to MIDI messages. SensorLog streams CSV values - comma-separated and then further delimited by line feed characters. I broke up the lines of data, and was able to convert the accelerometer readings to float values. Here too the learning was iterative: I was pleased to discover JUCE's NormalisableRange class, which appeared to let me map my accelerometer values to the 0-127 range MIDI requires, then startled when vigorous arm movements caused my program to crash!",{"type":22,"tag":31,"props":458,"children":459},{},[460],{"type":28,"value":461},"The problem was that I hadn't fully understood how the accelerometer values worked. I'd thought they might be ranging from -1.0 to 1.0, based on my cursory observations, but they're actually unbounded; 1.0 simply means acceleration equal to gravity, so quick movements can easily generate three or four times that value. I considered those movements to be outliers, and simply filtered them out. It was hard to imagine I'd be wildly swinging my fretting hand. If Pete Townsend wants this for his right arm, I can expand my range a bit! Accelerometer values also seem to depend upon the orientation within the gravitational field, so the watch at rest reports a non-zero value, and when upside down, a different value; roughly the inverse of the first.",{"type":22,"tag":31,"props":463,"children":464},{},[465],{"type":28,"value":466},"At this point I was ready to test - my iterative process had allowed me to check various components of the project along the way so I had some confidence that it would work pretty well.",{"type":22,"tag":23,"props":468,"children":470},{"id":469},"results",[471],{"type":28,"value":472},"Results",{"type":22,"tag":31,"props":474,"children":475},{},[476],{"type":22,"tag":64,"props":477,"children":480},{"href":478,"rel":479},"https://youtu.be/g5aaT5ytM3Q?si=mJVD1hVN3RHSJTWD",[68],[481],{"type":22,"tag":482,"props":483,"children":486},"img",{"alt":484,"src":485},"Performance","/asherbrooke/2020-4/img/Performance.jpg",[],{"type":22,"tag":31,"props":488,"children":489},{},[490],{"type":28,"value":491},"The results can be seen in the linked videos, and are really exciting to me. After just a few evenings of effort I have a surprisingly musical tool. I see many possible next steps; trying different sensors (possibly simultaneously), using other effects, scaling the controller data in different ways, and simply jamming with it for a while to see how my relationship with the tool evolves. The next steps will also be iterative, and perhaps documented here. I can already see that one challenge will be balancing my urge to keep tweaking against the goal of actually building something that others can use.",{"type":22,"tag":31,"props":493,"children":494},{},[495,497,504],{"type":28,"value":496},"Here's a ",{"type":22,"tag":64,"props":498,"children":501},{"href":499,"rel":500},"https://youtu.be/jTOcGLFNTmo",[68],[502],{"type":28,"value":503},"quick video",{"type":28,"value":505}," of the sensor data changing the sound of a solo guitar.",{"type":22,"tag":31,"props":507,"children":508},{},[509,510,517,519,526],{"type":28,"value":496},{"type":22,"tag":64,"props":511,"children":514},{"href":512,"rel":513},"https://youtu.be/g5aaT5ytM3Q",[68],[515],{"type":28,"value":516},"longer performance demonstration",{"type":28,"value":518},", featuring a song I wrote and recorded ",{"type":22,"tag":64,"props":520,"children":523},{"href":521,"rel":522},"https://youtu.be/Jc-J-T5gQBQ",[68],[524],{"type":28,"value":525},"once before",{"type":28,"value":527}," without the wah effect.",{"type":22,"tag":31,"props":529,"children":530},{},[531],{"type":22,"tag":288,"props":532,"children":533},{},[534],{"type":28,"value":535},"Photos courtesy of the author.",{"title":8,"searchDepth":255,"depth":255,"links":537},[538,539,544],{"id":299,"depth":258,"text":302},{"id":349,"depth":258,"text":352,"children":540},[541,542,543],{"id":371,"depth":255,"text":374},{"id":408,"depth":255,"text":411},{"id":419,"depth":255,"text":422},{"id":469,"depth":258,"text":472},"content:asherbrooke:2020-4:watchwah.md","asherbrooke/2020-4/watchwah.md","asherbrooke/2020-4/watchwah",{"user":549,"name":550},"asherbrooke","Andrew Sherbrooke",{"_path":552,"_dir":553,"_draft":7,"_partial":7,"_locale":8,"title":554,"description":555,"publishDate":556,"tags":557,"image":559,"excerpt":555,"body":560,"_type":262,"_id":725,"_source":264,"_file":726,"_stem":727,"_extension":267,"author":728},"/shuey/2012-07/reset-button","2012-07","The Reset Button","Horace Dediu of Asymco has been publishing some fantastic insights and analysis of the mobile market in the past few weeks. I linked to some of Dediu's analysis of the Economics of Android in an earlier post, and since then he's updated his work with the latest data and is studying RIM and Microsoft's efforts in the space as well.","2012-07-19",[558,15,279],"android","/shuey/2012-07/img/kevin.jpg",{"type":19,"children":561,"toc":723},[562,585,599,604,627,677,689,703,708],{"type":22,"tag":31,"props":563,"children":564},{},[565,567,574,576,583],{"type":28,"value":566},"Horace Dediu of ",{"type":22,"tag":64,"props":568,"children":571},{"href":569,"rel":570},"http://asymco.com",[68],[572],{"type":28,"value":573},"Asymco",{"type":28,"value":575}," has been publishing some fantastic insights and analysis of the mobile market in the past few weeks. I linked to some of Dediu's analysis of the ",{"type":22,"tag":64,"props":577,"children":580},{"href":578,"rel":579},"http://blog.artlogic.com/2012/05/17/the-economics-of-android/",[68],[581],{"type":28,"value":582},"Economics of Android",{"type":28,"value":584}," in an earlier post, and since then he's updated his work with the latest data and is studying RIM and Microsoft's efforts in the space as well.",{"type":22,"tag":31,"props":586,"children":587},{},[588,590,597],{"type":28,"value":589},"The recent episode of ",{"type":22,"tag":64,"props":591,"children":594},{"href":592,"rel":593},"http://5by5.tv/criticalpath/45",[68],[595],{"type":28,"value":596},"The Critical Path \"Management vs. Leadership\"",{"type":28,"value":598}," is simply fantastic. In the episode he posits that management is the process of running the day to day operations, of keeping a well organized system moving. Leadership on the other hand, is about disruption, about what's next, about bold moves. He captures this with the phrase, \"pressing the reset button\". With these definitions in mind, a successful leader is one who disrupts their business at its peak, and unsuccessful ones wait too long to make any bold moves. Dediu cites the famous example of Steve Jobs killing off the popular iPod Mini line and wonders if Apple is now \"pressing the reset button\" on the iPad as it dominates the tablet market.",{"type":22,"tag":31,"props":600,"children":601},{},[602],{"type":28,"value":603},"With that in mind, what have some of Apple's competitors been up to?",{"type":22,"tag":31,"props":605,"children":606},{},[607,609,616,618,625],{"type":28,"value":608},"RIM is making desperate, not bold moves, and possibly far too late. It's considering selling its handset business, BlackBerry OS 10 is delayed, and it's ",{"type":22,"tag":64,"props":610,"children":613},{"href":611,"rel":612},"http://www.businessweek.com/videos/2012-07-10/rim-to-sell-corporate-jet",[68],[614],{"type":28,"value":615},"selling a corporate jet to save some cash",{"type":28,"value":617},". It's stock price has fallen to record lows and the company just ",{"type":22,"tag":64,"props":619,"children":622},{"href":620,"rel":621},"http://www.morningstar.com/advisor/t/59341272/rim-found-guilty-of-infringing-mformation-patent.htm",[68],[623],{"type":28,"value":624},"lost a patent lawsuit to the tune of $142.7M",{"type":28,"value":626},".",{"type":22,"tag":31,"props":628,"children":629},{},[630,632,639,641,648,650,657,659,666,668,675],{"type":28,"value":631},"Microsoft is ",{"type":22,"tag":64,"props":633,"children":636},{"href":634,"rel":635},"http://www.bloomberg.com/news/2011-03-07/microsoft-is-said-to-pay-nokia-more-than-1-billion-under-software-accord.html",[68],[637],{"type":28,"value":638},"tied closely to Nokia",{"type":28,"value":640}," who bet heavily on the Lumia series of smartphones. Estimates show that ",{"type":22,"tag":64,"props":642,"children":645},{"href":643,"rel":644},"http://www.asymco.com/2012/07/19/how-many-lumia-phones-were-shipped-in-the-us/",[68],[646],{"type":28,"value":647},"400k to 1M Lumias were sold in the US",{"type":28,"value":649}," (updated 7/19/12 at 3:02pm) ",{"type":22,"tag":64,"props":651,"children":654},{"href":652,"rel":653},"http://www.asymco.com/2012/07/13/how-many-lumia/",[68],[655],{"type":28,"value":656},"that only 330k Lumias were sold in the US",{"type":28,"value":658}," and their launch partner AT&T is now ",{"type":22,"tag":64,"props":660,"children":663},{"href":661,"rel":662},"http://news.cnet.com/8301-1035_3-57472577-94/at-t-slashes-nokia-lumia-900-price-by-half/?tag=mncol;txt",[68],[664],{"type":28,"value":665},"selling them for half price.",{"type":28,"value":667}," Making matters worse, the Lumias aren't able to be upgraded to the newly demoed Windows Mobile 8 that was introduced alongside the new Surface tablet. In addition to competing with Apple's iPad, the Surface is set to compete against Microsoft's OEM partners, which ",{"type":22,"tag":64,"props":669,"children":672},{"href":670,"rel":671},"http://news.cnet.com/8301-10805_3-57469903-75/microsofts-surface-is-a-design-point-says-ceo/",[68],[673],{"type":28,"value":674},"they've tried to downplay",{"type":28,"value":676},". Following the failed Zune and Kin brands, the struggling Lumia line which they backed heavily, the Surface brand has its work cut out for itself. Pricing and a release date haven't been announced yet, but it will be interesting to see when it ships and what it will retail for.",{"type":22,"tag":31,"props":678,"children":679},{},[680,687],{"type":22,"tag":64,"props":681,"children":684},{"href":682,"rel":683},"http://www.asymco.com/2012/07/16/from-bad-to-worse-and-from-good-to-great/",[68],[685],{"type":28,"value":686},"Samsung is making most of the money",{"type":28,"value":688}," in the Android ecosystem and companies like HTC are suffering significant losses. In Dediu's analysis of HTC's woes it looks as if they've struggled to match Samsung in volume in their transition from a relatively low volume Windows Mobile smartphone business to Android. An area that Apple has excelled at, thanks largely to Tim Cook, is in volume, and they've been able to quickly ramp up production, purchase components in unheard of quantities, and are investing billions in their production facilities. This is an area that Microsoft may struggle in as well. Their Xbox business doesn't come close in size to the iPad or iPhone in units produced.",{"type":22,"tag":31,"props":690,"children":691},{},[692,694,701],{"type":28,"value":693},"Google's new Android tablet, the ",{"type":22,"tag":64,"props":695,"children":698},{"href":696,"rel":697},"http://www.google.com/nexus/#/7",[68],[699],{"type":28,"value":700},"Google Nexus 7",{"type":28,"value":702}," is getting good reviews, but looks to compete more with Amazon's Kindle Fire than the iPad. However, both devices are US only for the most part due to the lack of content distribution deals internationally which Apple has worked hard to establish. The US market is becoming an increasingly smaller piece of the worldwide mobile market so it will be interesting to see how Amazon and Google respond.",{"type":22,"tag":31,"props":704,"children":705},{},[706],{"type":28,"value":707},"Apple is set to release their third quarter earnings next Tuesday and rumors are swirling that a 7.85\" iPad and iPhone 5 will be announced and ship in September or October.  Will these products be an evolution of the current lineup or will there be some indications that the reset button has been pressed in Cupertino?",{"type":22,"tag":31,"props":709,"children":710},{},[711],{"type":22,"tag":288,"props":712,"children":713},{},[714,716],{"type":28,"value":715},"Image credit: ",{"type":22,"tag":64,"props":717,"children":720},{"href":718,"rel":719},"http://www.flickr.com/photos/fortunelivemedia/",[68],[721],{"type":28,"value":722},"Fortune Live Media",{"title":8,"searchDepth":255,"depth":255,"links":724},[],"content:shuey:2012-07:reset-button.md","shuey/2012-07/reset-button.md","shuey/2012-07/reset-button",{"user":729,"name":730},"shuey","Steven Huey",{"_path":732,"_dir":553,"_draft":7,"_partial":7,"_locale":8,"title":733,"description":734,"publishDate":735,"tags":736,"image":738,"excerpt":734,"body":739,"_type":262,"_id":2737,"_source":264,"_file":2738,"_stem":2739,"_extension":267,"author":2740},"/shuey/2012-07/mixer","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",[15,737,279],"cocoa","/shuey/2012-07/img/mixer-screenshot.jpg",{"type":19,"children":740,"toc":2735},[741,755,787,796,819,842,1783,1806,1814,2002,2007,2015,2188,2193,2201,2304,2309,2317,2688,2711,2719,2724,2729],{"type":22,"tag":31,"props":742,"children":743},{},[744,746,753],{"type":28,"value":745},"In iOS 4.0 Apple introduced the ",{"type":22,"tag":64,"props":747,"children":750},{"href":748,"rel":749},"https://developer.apple.com/library/mac/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188",[68],[751],{"type":28,"value":752},"AV Foundation APIs",{"type":28,"value":754}," 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":22,"tag":31,"props":756,"children":757},{},[758,760,767,769,776,778,785],{"type":28,"value":759},"The code for the project is ",{"type":22,"tag":64,"props":761,"children":764},{"href":762,"rel":763},"https://github.com/stevenhuey/ALMixer",[68],[765],{"type":28,"value":766},"available on GitHub",{"type":28,"value":768},". 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":22,"tag":64,"props":770,"children":773},{"href":771,"rel":772},"https://github.com/stevenhuey/ALMixer/blob/master/README.md",[68],[774],{"type":28,"value":775},"ReadMe.md",{"type":28,"value":777}," 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":22,"tag":64,"props":779,"children":782},{"href":780,"rel":781},"https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226",[68],[783],{"type":28,"value":784},"ARC",{"type":28,"value":786}," (Automatic Reference Counting).",{"type":22,"tag":31,"props":788,"children":789},{},[790],{"type":22,"tag":791,"props":792,"children":793},"strong",{},[794],{"type":28,"value":795},"Setup",{"type":22,"tag":31,"props":797,"children":798},{},[799,801,808,810,817],{"type":28,"value":800},"To start we'll create an ",{"type":22,"tag":64,"props":802,"children":805},{"href":803,"rel":804},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableComposition_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40009526",[68],[806],{"type":28,"value":807},"AVMutableComposition",{"type":28,"value":809}," instance and two ",{"type":22,"tag":64,"props":811,"children":814},{"href":812,"rel":813},"https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/Reference/Reference.html",[68],[815],{"type":28,"value":816},"NSMutableDictionaries",{"type":28,"value":818},". 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":22,"tag":31,"props":820,"children":821},{},[822,824,831,833,840],{"type":28,"value":823},"Our audio tracks are loaded from the Resources directory within the app bundle using the ",{"type":22,"tag":64,"props":825,"children":828},{"href":826,"rel":827},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVURLAsset_Class/Reference/Reference.html",[68],[829],{"type":28,"value":830},"AVURLAsset",{"type":28,"value":832}," class and then used to create an ",{"type":22,"tag":64,"props":834,"children":837},{"href":835,"rel":836},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableCompositionTrack_Class/Reference/Reference.html",[68],[838],{"type":28,"value":839},"AVMutableCompositionTrack",{"type":28,"value":841}," 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":22,"tag":104,"props":843,"children":847},{"className":844,"code":845,"language":846,"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",[848],{"type":22,"tag":47,"props":849,"children":850},{"__ignoreMap":8},[851,863,883,892,926,955,963,972,1057,1094,1102,1135,1144,1207,1228,1236,1272,1290,1298,1316,1339,1379,1397,1416,1424,1438,1447,1471,1480,1488,1497,1524,1542,1550,1559,1601,1610,1618,1627,1636,1672,1690,1712,1730,1748,1756],{"type":22,"tag":852,"props":853,"children":856},"span",{"class":854,"line":855},"line",1,[857],{"type":22,"tag":852,"props":858,"children":860},{"style":859},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[861],{"type":28,"value":862},"// Setup\n",{"type":22,"tag":852,"props":864,"children":865},{"class":854,"line":258},[866,872,878],{"type":22,"tag":852,"props":867,"children":869},{"style":868},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[870],{"type":28,"value":871},"   _composition ",{"type":22,"tag":852,"props":873,"children":875},{"style":874},"--shiki-default:#D73A49;--shiki-dark:#F97583",[876],{"type":28,"value":877},"=",{"type":22,"tag":852,"props":879,"children":880},{"style":868},[881],{"type":28,"value":882}," [AVMutableComposition composition];\n",{"type":22,"tag":852,"props":884,"children":885},{"class":854,"line":255},[886],{"type":22,"tag":852,"props":887,"children":889},{"emptyLinePlaceholder":888},true,[890],{"type":28,"value":891},"\n",{"type":22,"tag":852,"props":893,"children":895},{"class":854,"line":894},4,[896,901,905,910,915,921],{"type":22,"tag":852,"props":897,"children":898},{"style":868},[899],{"type":28,"value":900},"   _audioMixValues ",{"type":22,"tag":852,"props":902,"children":903},{"style":874},[904],{"type":28,"value":877},{"type":22,"tag":852,"props":906,"children":907},{"style":868},[908],{"type":28,"value":909}," [[NSMutableDictionary alloc] initWithCapacity",{"type":22,"tag":852,"props":911,"children":912},{"style":874},[913],{"type":28,"value":914},":",{"type":22,"tag":852,"props":916,"children":918},{"style":917},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[919],{"type":28,"value":920},"0",{"type":22,"tag":852,"props":922,"children":923},{"style":868},[924],{"type":28,"value":925},"];\n",{"type":22,"tag":852,"props":927,"children":929},{"class":854,"line":928},5,[930,935,939,943,947,951],{"type":22,"tag":852,"props":931,"children":932},{"style":868},[933],{"type":28,"value":934},"   _audioMixTrackIDs ",{"type":22,"tag":852,"props":936,"children":937},{"style":874},[938],{"type":28,"value":877},{"type":22,"tag":852,"props":940,"children":941},{"style":868},[942],{"type":28,"value":909},{"type":22,"tag":852,"props":944,"children":945},{"style":874},[946],{"type":28,"value":914},{"type":22,"tag":852,"props":948,"children":949},{"style":917},[950],{"type":28,"value":920},{"type":22,"tag":852,"props":952,"children":953},{"style":868},[954],{"type":28,"value":925},{"type":22,"tag":852,"props":956,"children":958},{"class":854,"line":957},6,[959],{"type":22,"tag":852,"props":960,"children":961},{"emptyLinePlaceholder":888},[962],{"type":28,"value":891},{"type":22,"tag":852,"props":964,"children":966},{"class":854,"line":965},7,[967],{"type":22,"tag":852,"props":968,"children":969},{"style":859},[970],{"type":28,"value":971},"   // Insert the audio tracks into our composition\n",{"type":22,"tag":852,"props":973,"children":975},{"class":854,"line":974},8,[976,981,986,991,995,1000,1004,1009,1015,1020,1025,1029,1034,1038,1043,1048,1053],{"type":22,"tag":852,"props":977,"children":978},{"style":868},[979],{"type":28,"value":980},"   NSArray",{"type":22,"tag":852,"props":982,"children":983},{"style":874},[984],{"type":28,"value":985},"*",{"type":22,"tag":852,"props":987,"children":988},{"style":868},[989],{"type":28,"value":990}," tracks ",{"type":22,"tag":852,"props":992,"children":993},{"style":874},[994],{"type":28,"value":877},{"type":22,"tag":852,"props":996,"children":997},{"style":868},[998],{"type":28,"value":999}," [NSArray arrayWithObjects",{"type":22,"tag":852,"props":1001,"children":1002},{"style":874},[1003],{"type":28,"value":914},{"type":22,"tag":852,"props":1005,"children":1006},{"style":868},[1007],{"type":28,"value":1008},"@",{"type":22,"tag":852,"props":1010,"children":1012},{"style":1011},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[1013],{"type":28,"value":1014},"\"track1\"",{"type":22,"tag":852,"props":1016,"children":1017},{"style":868},[1018],{"type":28,"value":1019},", @",{"type":22,"tag":852,"props":1021,"children":1022},{"style":1011},[1023],{"type":28,"value":1024},"\"track2\"",{"type":22,"tag":852,"props":1026,"children":1027},{"style":868},[1028],{"type":28,"value":1019},{"type":22,"tag":852,"props":1030,"children":1031},{"style":1011},[1032],{"type":28,"value":1033},"\"track3\"",{"type":22,"tag":852,"props":1035,"children":1036},{"style":868},[1037],{"type":28,"value":1019},{"type":22,"tag":852,"props":1039,"children":1040},{"style":1011},[1041],{"type":28,"value":1042},"\"track4\"",{"type":22,"tag":852,"props":1044,"children":1045},{"style":868},[1046],{"type":28,"value":1047},", ",{"type":22,"tag":852,"props":1049,"children":1050},{"style":917},[1051],{"type":28,"value":1052},"nil",{"type":22,"tag":852,"props":1054,"children":1055},{"style":868},[1056],{"type":28,"value":925},{"type":22,"tag":852,"props":1058,"children":1060},{"class":854,"line":1059},9,[1061,1066,1070,1075,1079,1084,1089],{"type":22,"tag":852,"props":1062,"children":1063},{"style":868},[1064],{"type":28,"value":1065},"   NSString",{"type":22,"tag":852,"props":1067,"children":1068},{"style":874},[1069],{"type":28,"value":985},{"type":22,"tag":852,"props":1071,"children":1072},{"style":868},[1073],{"type":28,"value":1074}," audioFileType ",{"type":22,"tag":852,"props":1076,"children":1077},{"style":874},[1078],{"type":28,"value":877},{"type":22,"tag":852,"props":1080,"children":1081},{"style":868},[1082],{"type":28,"value":1083}," @",{"type":22,"tag":852,"props":1085,"children":1086},{"style":1011},[1087],{"type":28,"value":1088},"\"wav\"",{"type":22,"tag":852,"props":1090,"children":1091},{"style":868},[1092],{"type":28,"value":1093},";\n",{"type":22,"tag":852,"props":1095,"children":1097},{"class":854,"line":1096},10,[1098],{"type":22,"tag":852,"props":1099,"children":1100},{"emptyLinePlaceholder":888},[1101],{"type":28,"value":891},{"type":22,"tag":852,"props":1103,"children":1105},{"class":854,"line":1104},11,[1106,1111,1116,1120,1125,1130],{"type":22,"tag":852,"props":1107,"children":1108},{"style":874},[1109],{"type":28,"value":1110},"   for",{"type":22,"tag":852,"props":1112,"children":1113},{"style":868},[1114],{"type":28,"value":1115}," (NSString",{"type":22,"tag":852,"props":1117,"children":1118},{"style":874},[1119],{"type":28,"value":985},{"type":22,"tag":852,"props":1121,"children":1122},{"style":868},[1123],{"type":28,"value":1124}," trackName ",{"type":22,"tag":852,"props":1126,"children":1127},{"style":874},[1128],{"type":28,"value":1129},"in",{"type":22,"tag":852,"props":1131,"children":1132},{"style":868},[1133],{"type":28,"value":1134}," tracks)\n",{"type":22,"tag":852,"props":1136,"children":1138},{"class":854,"line":1137},12,[1139],{"type":22,"tag":852,"props":1140,"children":1141},{"style":868},[1142],{"type":28,"value":1143},"   {\n",{"type":22,"tag":852,"props":1145,"children":1147},{"class":854,"line":1146},13,[1148,1153,1157,1162,1166,1171,1175,1180,1184,1189,1193,1198,1202],{"type":22,"tag":852,"props":1149,"children":1150},{"style":868},[1151],{"type":28,"value":1152},"      AVURLAsset",{"type":22,"tag":852,"props":1154,"children":1155},{"style":874},[1156],{"type":28,"value":985},{"type":22,"tag":852,"props":1158,"children":1159},{"style":868},[1160],{"type":28,"value":1161}," audioAsset ",{"type":22,"tag":852,"props":1163,"children":1164},{"style":874},[1165],{"type":28,"value":877},{"type":22,"tag":852,"props":1167,"children":1168},{"style":868},[1169],{"type":28,"value":1170}," [[AVURLAsset alloc]initWithURL",{"type":22,"tag":852,"props":1172,"children":1173},{"style":874},[1174],{"type":28,"value":914},{"type":22,"tag":852,"props":1176,"children":1177},{"style":868},[1178],{"type":28,"value":1179},"[NSURL fileURLWithPath",{"type":22,"tag":852,"props":1181,"children":1182},{"style":874},[1183],{"type":28,"value":914},{"type":22,"tag":852,"props":1185,"children":1186},{"style":868},[1187],{"type":28,"value":1188},"[[NSBundle mainBundle] pathForResource",{"type":22,"tag":852,"props":1190,"children":1191},{"style":874},[1192],{"type":28,"value":914},{"type":22,"tag":852,"props":1194,"children":1195},{"style":868},[1196],{"type":28,"value":1197},"trackName ofType",{"type":22,"tag":852,"props":1199,"children":1200},{"style":874},[1201],{"type":28,"value":914},{"type":22,"tag":852,"props":1203,"children":1204},{"style":868},[1205],{"type":28,"value":1206},"audioFileType]]\n",{"type":22,"tag":852,"props":1208,"children":1210},{"class":854,"line":1209},14,[1211,1216,1220,1224],{"type":22,"tag":852,"props":1212,"children":1213},{"style":868},[1214],{"type":28,"value":1215},"                                                      options",{"type":22,"tag":852,"props":1217,"children":1218},{"style":874},[1219],{"type":28,"value":914},{"type":22,"tag":852,"props":1221,"children":1222},{"style":917},[1223],{"type":28,"value":1052},{"type":22,"tag":852,"props":1225,"children":1226},{"style":868},[1227],{"type":28,"value":925},{"type":22,"tag":852,"props":1229,"children":1231},{"class":854,"line":1230},15,[1232],{"type":22,"tag":852,"props":1233,"children":1234},{"emptyLinePlaceholder":888},[1235],{"type":28,"value":891},{"type":22,"tag":852,"props":1237,"children":1239},{"class":854,"line":1238},16,[1240,1245,1249,1254,1258,1263,1267],{"type":22,"tag":852,"props":1241,"children":1242},{"style":868},[1243],{"type":28,"value":1244},"      AVMutableCompositionTrack",{"type":22,"tag":852,"props":1246,"children":1247},{"style":874},[1248],{"type":28,"value":985},{"type":22,"tag":852,"props":1250,"children":1251},{"style":868},[1252],{"type":28,"value":1253}," audioTrack ",{"type":22,"tag":852,"props":1255,"children":1256},{"style":874},[1257],{"type":28,"value":877},{"type":22,"tag":852,"props":1259,"children":1260},{"style":868},[1261],{"type":28,"value":1262}," [_composition addMutableTrackWithMediaType",{"type":22,"tag":852,"props":1264,"children":1265},{"style":874},[1266],{"type":28,"value":914},{"type":22,"tag":852,"props":1268,"children":1269},{"style":868},[1270],{"type":28,"value":1271},"AVMediaTypeAudio\n",{"type":22,"tag":852,"props":1273,"children":1275},{"class":854,"line":1274},17,[1276,1281,1285],{"type":22,"tag":852,"props":1277,"children":1278},{"style":868},[1279],{"type":28,"value":1280},"                                                                        preferredTrackID",{"type":22,"tag":852,"props":1282,"children":1283},{"style":874},[1284],{"type":28,"value":914},{"type":22,"tag":852,"props":1286,"children":1287},{"style":868},[1288],{"type":28,"value":1289},"kCMPersistentTrackID_Invalid];\n",{"type":22,"tag":852,"props":1291,"children":1293},{"class":854,"line":1292},18,[1294],{"type":22,"tag":852,"props":1295,"children":1296},{"emptyLinePlaceholder":888},[1297],{"type":28,"value":891},{"type":22,"tag":852,"props":1299,"children":1301},{"class":854,"line":1300},19,[1302,1307,1311],{"type":22,"tag":852,"props":1303,"children":1304},{"style":868},[1305],{"type":28,"value":1306},"      NSError",{"type":22,"tag":852,"props":1308,"children":1309},{"style":874},[1310],{"type":28,"value":985},{"type":22,"tag":852,"props":1312,"children":1313},{"style":868},[1314],{"type":28,"value":1315}," error;\n",{"type":22,"tag":852,"props":1317,"children":1319},{"class":854,"line":1318},20,[1320,1325,1329,1334],{"type":22,"tag":852,"props":1321,"children":1322},{"style":868},[1323],{"type":28,"value":1324},"      [audioTrack insertTimeRange",{"type":22,"tag":852,"props":1326,"children":1327},{"style":874},[1328],{"type":28,"value":914},{"type":22,"tag":852,"props":1330,"children":1331},{"style":917},[1332],{"type":28,"value":1333},"CMTimeRangeMake",{"type":22,"tag":852,"props":1335,"children":1336},{"style":868},[1337],{"type":28,"value":1338},"(kCMTimeZero, audioAsset.duration)\n",{"type":22,"tag":852,"props":1340,"children":1342},{"class":854,"line":1341},21,[1343,1348,1352,1357,1361,1366,1370,1374],{"type":22,"tag":852,"props":1344,"children":1345},{"style":868},[1346],{"type":28,"value":1347},"                          ofTrack",{"type":22,"tag":852,"props":1349,"children":1350},{"style":874},[1351],{"type":28,"value":914},{"type":22,"tag":852,"props":1353,"children":1354},{"style":868},[1355],{"type":28,"value":1356},"[[audioAsset tracksWithMediaType",{"type":22,"tag":852,"props":1358,"children":1359},{"style":874},[1360],{"type":28,"value":914},{"type":22,"tag":852,"props":1362,"children":1363},{"style":868},[1364],{"type":28,"value":1365},"AVMediaTypeAudio]objectAtIndex",{"type":22,"tag":852,"props":1367,"children":1368},{"style":874},[1369],{"type":28,"value":914},{"type":22,"tag":852,"props":1371,"children":1372},{"style":917},[1373],{"type":28,"value":920},{"type":22,"tag":852,"props":1375,"children":1376},{"style":868},[1377],{"type":28,"value":1378},"]\n",{"type":22,"tag":852,"props":1380,"children":1382},{"class":854,"line":1381},22,[1383,1388,1392],{"type":22,"tag":852,"props":1384,"children":1385},{"style":868},[1386],{"type":28,"value":1387},"                           atTime",{"type":22,"tag":852,"props":1389,"children":1390},{"style":874},[1391],{"type":28,"value":914},{"type":22,"tag":852,"props":1393,"children":1394},{"style":868},[1395],{"type":28,"value":1396},"kCMTimeZero\n",{"type":22,"tag":852,"props":1398,"children":1400},{"class":854,"line":1399},23,[1401,1406,1411],{"type":22,"tag":852,"props":1402,"children":1403},{"style":868},[1404],{"type":28,"value":1405},"                            error",{"type":22,"tag":852,"props":1407,"children":1408},{"style":874},[1409],{"type":28,"value":1410},":&",{"type":22,"tag":852,"props":1412,"children":1413},{"style":868},[1414],{"type":28,"value":1415},"error];\n",{"type":22,"tag":852,"props":1417,"children":1419},{"class":854,"line":1418},24,[1420],{"type":22,"tag":852,"props":1421,"children":1422},{"emptyLinePlaceholder":888},[1423],{"type":28,"value":891},{"type":22,"tag":852,"props":1425,"children":1427},{"class":854,"line":1426},25,[1428,1433],{"type":22,"tag":852,"props":1429,"children":1430},{"style":874},[1431],{"type":28,"value":1432},"      if",{"type":22,"tag":852,"props":1434,"children":1435},{"style":868},[1436],{"type":28,"value":1437}," (error)\n",{"type":22,"tag":852,"props":1439,"children":1441},{"class":854,"line":1440},26,[1442],{"type":22,"tag":852,"props":1443,"children":1444},{"style":868},[1445],{"type":28,"value":1446},"      {\n",{"type":22,"tag":852,"props":1448,"children":1450},{"class":854,"line":1449},27,[1451,1456,1461,1466],{"type":22,"tag":852,"props":1452,"children":1453},{"style":917},[1454],{"type":28,"value":1455},"         NSLog",{"type":22,"tag":852,"props":1457,"children":1458},{"style":868},[1459],{"type":28,"value":1460},"(@",{"type":22,"tag":852,"props":1462,"children":1463},{"style":1011},[1464],{"type":28,"value":1465},"\"%@\"",{"type":22,"tag":852,"props":1467,"children":1468},{"style":868},[1469],{"type":28,"value":1470},", [error localizedDescription]);\n",{"type":22,"tag":852,"props":1472,"children":1474},{"class":854,"line":1473},28,[1475],{"type":22,"tag":852,"props":1476,"children":1477},{"style":868},[1478],{"type":28,"value":1479},"      }\n",{"type":22,"tag":852,"props":1481,"children":1483},{"class":854,"line":1482},29,[1484],{"type":22,"tag":852,"props":1485,"children":1486},{"emptyLinePlaceholder":888},[1487],{"type":28,"value":891},{"type":22,"tag":852,"props":1489,"children":1491},{"class":854,"line":1490},30,[1492],{"type":22,"tag":852,"props":1493,"children":1494},{"style":859},[1495],{"type":28,"value":1496},"      // Store the track IDs as track name -> track ID\n",{"type":22,"tag":852,"props":1498,"children":1500},{"class":854,"line":1499},31,[1501,1506,1510,1515,1519],{"type":22,"tag":852,"props":1502,"children":1503},{"style":868},[1504],{"type":28,"value":1505},"      [_audioMixTrackIDs setValue",{"type":22,"tag":852,"props":1507,"children":1508},{"style":874},[1509],{"type":28,"value":914},{"type":22,"tag":852,"props":1511,"children":1512},{"style":868},[1513],{"type":28,"value":1514},"[NSNumber numberWithInteger",{"type":22,"tag":852,"props":1516,"children":1517},{"style":874},[1518],{"type":28,"value":914},{"type":22,"tag":852,"props":1520,"children":1521},{"style":868},[1522],{"type":28,"value":1523},"audioTrack.trackID]\n",{"type":22,"tag":852,"props":1525,"children":1527},{"class":854,"line":1526},32,[1528,1533,1537],{"type":22,"tag":852,"props":1529,"children":1530},{"style":868},[1531],{"type":28,"value":1532},"                           forKey",{"type":22,"tag":852,"props":1534,"children":1535},{"style":874},[1536],{"type":28,"value":914},{"type":22,"tag":852,"props":1538,"children":1539},{"style":868},[1540],{"type":28,"value":1541},"trackName];\n",{"type":22,"tag":852,"props":1543,"children":1545},{"class":854,"line":1544},33,[1546],{"type":22,"tag":852,"props":1547,"children":1548},{"emptyLinePlaceholder":888},[1549],{"type":28,"value":891},{"type":22,"tag":852,"props":1551,"children":1553},{"class":854,"line":1552},34,[1554],{"type":22,"tag":852,"props":1555,"children":1556},{"style":859},[1557],{"type":28,"value":1558},"      // Set the volume to 1.0 (max) for the track\n",{"type":22,"tag":852,"props":1560,"children":1562},{"class":854,"line":1561},35,[1563,1568,1573,1578,1582,1588,1593,1597],{"type":22,"tag":852,"props":1564,"children":1565},{"style":868},[1566],{"type":28,"value":1567},"      [",{"type":22,"tag":852,"props":1569,"children":1570},{"style":917},[1571],{"type":28,"value":1572},"self",{"type":22,"tag":852,"props":1574,"children":1575},{"style":868},[1576],{"type":28,"value":1577}," setVolume",{"type":22,"tag":852,"props":1579,"children":1580},{"style":874},[1581],{"type":28,"value":914},{"type":22,"tag":852,"props":1583,"children":1585},{"style":1584},"--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic",[1586],{"type":28,"value":1587},"1.0f",{"type":22,"tag":852,"props":1589,"children":1590},{"style":868},[1591],{"type":28,"value":1592}," forTrack",{"type":22,"tag":852,"props":1594,"children":1595},{"style":874},[1596],{"type":28,"value":914},{"type":22,"tag":852,"props":1598,"children":1599},{"style":868},[1600],{"type":28,"value":1541},{"type":22,"tag":852,"props":1602,"children":1604},{"class":854,"line":1603},36,[1605],{"type":22,"tag":852,"props":1606,"children":1607},{"style":868},[1608],{"type":28,"value":1609},"   }\n",{"type":22,"tag":852,"props":1611,"children":1613},{"class":854,"line":1612},37,[1614],{"type":22,"tag":852,"props":1615,"children":1616},{"emptyLinePlaceholder":888},[1617],{"type":28,"value":891},{"type":22,"tag":852,"props":1619,"children":1621},{"class":854,"line":1620},38,[1622],{"type":22,"tag":852,"props":1623,"children":1624},{"style":859},[1625],{"type":28,"value":1626},"   // Create a player for our composition of audio tracks. We observe the status so\n",{"type":22,"tag":852,"props":1628,"children":1630},{"class":854,"line":1629},39,[1631],{"type":22,"tag":852,"props":1632,"children":1633},{"style":859},[1634],{"type":28,"value":1635},"   // we know when the player is ready to play\n",{"type":22,"tag":852,"props":1637,"children":1639},{"class":854,"line":1638},40,[1640,1645,1649,1654,1658,1663,1667],{"type":22,"tag":852,"props":1641,"children":1642},{"style":868},[1643],{"type":28,"value":1644},"   AVPlayerItem",{"type":22,"tag":852,"props":1646,"children":1647},{"style":874},[1648],{"type":28,"value":985},{"type":22,"tag":852,"props":1650,"children":1651},{"style":868},[1652],{"type":28,"value":1653}," playerItem ",{"type":22,"tag":852,"props":1655,"children":1656},{"style":874},[1657],{"type":28,"value":877},{"type":22,"tag":852,"props":1659,"children":1660},{"style":868},[1661],{"type":28,"value":1662}," [[AVPlayerItem alloc] initWithAsset",{"type":22,"tag":852,"props":1664,"children":1665},{"style":874},[1666],{"type":28,"value":914},{"type":22,"tag":852,"props":1668,"children":1669},{"style":868},[1670],{"type":28,"value":1671},"[_composition copy]];\n",{"type":22,"tag":852,"props":1673,"children":1675},{"class":854,"line":1674},41,[1676,1681,1685],{"type":22,"tag":852,"props":1677,"children":1678},{"style":868},[1679],{"type":28,"value":1680},"   [playerItem addObserver",{"type":22,"tag":852,"props":1682,"children":1683},{"style":874},[1684],{"type":28,"value":914},{"type":22,"tag":852,"props":1686,"children":1687},{"style":917},[1688],{"type":28,"value":1689},"self\n",{"type":22,"tag":852,"props":1691,"children":1693},{"class":854,"line":1692},42,[1694,1699,1703,1707],{"type":22,"tag":852,"props":1695,"children":1696},{"style":868},[1697],{"type":28,"value":1698},"                forKeyPath",{"type":22,"tag":852,"props":1700,"children":1701},{"style":874},[1702],{"type":28,"value":914},{"type":22,"tag":852,"props":1704,"children":1705},{"style":868},[1706],{"type":28,"value":1008},{"type":22,"tag":852,"props":1708,"children":1709},{"style":1011},[1710],{"type":28,"value":1711},"\"status\"\n",{"type":22,"tag":852,"props":1713,"children":1715},{"class":854,"line":1714},43,[1716,1721,1725],{"type":22,"tag":852,"props":1717,"children":1718},{"style":868},[1719],{"type":28,"value":1720},"                   options",{"type":22,"tag":852,"props":1722,"children":1723},{"style":874},[1724],{"type":28,"value":914},{"type":22,"tag":852,"props":1726,"children":1727},{"style":917},[1728],{"type":28,"value":1729},"0\n",{"type":22,"tag":852,"props":1731,"children":1733},{"class":854,"line":1732},44,[1734,1739,1743],{"type":22,"tag":852,"props":1735,"children":1736},{"style":868},[1737],{"type":28,"value":1738},"                   context",{"type":22,"tag":852,"props":1740,"children":1741},{"style":874},[1742],{"type":28,"value":914},{"type":22,"tag":852,"props":1744,"children":1745},{"style":868},[1746],{"type":28,"value":1747},"NULL];\n",{"type":22,"tag":852,"props":1749,"children":1751},{"class":854,"line":1750},45,[1752],{"type":22,"tag":852,"props":1753,"children":1754},{"emptyLinePlaceholder":888},[1755],{"type":28,"value":891},{"type":22,"tag":852,"props":1757,"children":1759},{"class":854,"line":1758},46,[1760,1765,1769,1774,1778],{"type":22,"tag":852,"props":1761,"children":1762},{"style":868},[1763],{"type":28,"value":1764},"   _player ",{"type":22,"tag":852,"props":1766,"children":1767},{"style":874},[1768],{"type":28,"value":877},{"type":22,"tag":852,"props":1770,"children":1771},{"style":868},[1772],{"type":28,"value":1773}," [[AVPlayer alloc] initWithPlayerItem",{"type":22,"tag":852,"props":1775,"children":1776},{"style":874},[1777],{"type":28,"value":914},{"type":22,"tag":852,"props":1779,"children":1780},{"style":868},[1781],{"type":28,"value":1782},"playerItem];\n",{"type":22,"tag":31,"props":1784,"children":1785},{},[1786,1788,1795,1797,1804],{"type":28,"value":1787},"Finally, we create an ",{"type":22,"tag":64,"props":1789,"children":1792},{"href":1790,"rel":1791},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayerItem_Class/Reference/Reference.html",[68],[1793],{"type":28,"value":1794},"AVPlayerItem",{"type":28,"value":1796}," using our AVMutableComposition, and use that to create a ",{"type":22,"tag":64,"props":1798,"children":1801},{"href":1799,"rel":1800},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayer_Class/Reference/Reference.html",[68],[1802],{"type":28,"value":1803},"AVPlayer",{"type":28,"value":1805}," 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":22,"tag":31,"props":1807,"children":1808},{},[1809],{"type":22,"tag":791,"props":1810,"children":1811},{},[1812],{"type":28,"value":1813},"Key Value Observing (KVO)",{"type":22,"tag":104,"props":1815,"children":1817},{"className":844,"code":1816,"language":846,"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",[1818],{"type":22,"tag":47,"props":1819,"children":1820},{"__ignoreMap":8},[1821,1897,1905,1936,1943,1965,1972,1980,1987,1994],{"type":22,"tag":852,"props":1822,"children":1823},{"class":854,"line":855},[1824,1829,1834,1838,1843,1847,1852,1856,1861,1865,1870,1874,1879,1883,1888,1892],{"type":22,"tag":852,"props":1825,"children":1826},{"style":874},[1827],{"type":28,"value":1828},"-",{"type":22,"tag":852,"props":1830,"children":1831},{"style":868},[1832],{"type":28,"value":1833}," (void)observeValueForKeyPath",{"type":22,"tag":852,"props":1835,"children":1836},{"style":874},[1837],{"type":28,"value":914},{"type":22,"tag":852,"props":1839,"children":1840},{"style":868},[1841],{"type":28,"value":1842},"(NSString ",{"type":22,"tag":852,"props":1844,"children":1845},{"style":874},[1846],{"type":28,"value":985},{"type":22,"tag":852,"props":1848,"children":1849},{"style":868},[1850],{"type":28,"value":1851},")keyPath ofObject",{"type":22,"tag":852,"props":1853,"children":1854},{"style":874},[1855],{"type":28,"value":914},{"type":22,"tag":852,"props":1857,"children":1858},{"style":868},[1859],{"type":28,"value":1860},"(id)object change",{"type":22,"tag":852,"props":1862,"children":1863},{"style":874},[1864],{"type":28,"value":914},{"type":22,"tag":852,"props":1866,"children":1867},{"style":868},[1868],{"type":28,"value":1869},"(NSDictionary ",{"type":22,"tag":852,"props":1871,"children":1872},{"style":874},[1873],{"type":28,"value":985},{"type":22,"tag":852,"props":1875,"children":1876},{"style":868},[1877],{"type":28,"value":1878},")change context",{"type":22,"tag":852,"props":1880,"children":1881},{"style":874},[1882],{"type":28,"value":914},{"type":22,"tag":852,"props":1884,"children":1885},{"style":868},[1886],{"type":28,"value":1887},"(void ",{"type":22,"tag":852,"props":1889,"children":1890},{"style":874},[1891],{"type":28,"value":985},{"type":22,"tag":852,"props":1893,"children":1894},{"style":868},[1895],{"type":28,"value":1896},")context\n",{"type":22,"tag":852,"props":1898,"children":1899},{"class":854,"line":258},[1900],{"type":22,"tag":852,"props":1901,"children":1902},{"style":868},[1903],{"type":28,"value":1904},"{\n",{"type":22,"tag":852,"props":1906,"children":1907},{"class":854,"line":255},[1908,1913,1918,1922,1926,1931],{"type":22,"tag":852,"props":1909,"children":1910},{"style":874},[1911],{"type":28,"value":1912},"   if",{"type":22,"tag":852,"props":1914,"children":1915},{"style":868},[1916],{"type":28,"value":1917}," ([keyPath isEqualToString",{"type":22,"tag":852,"props":1919,"children":1920},{"style":874},[1921],{"type":28,"value":914},{"type":22,"tag":852,"props":1923,"children":1924},{"style":868},[1925],{"type":28,"value":1008},{"type":22,"tag":852,"props":1927,"children":1928},{"style":1011},[1929],{"type":28,"value":1930},"\"status\"",{"type":22,"tag":852,"props":1932,"children":1933},{"style":868},[1934],{"type":28,"value":1935},"])\n",{"type":22,"tag":852,"props":1937,"children":1938},{"class":854,"line":894},[1939],{"type":22,"tag":852,"props":1940,"children":1941},{"style":868},[1942],{"type":28,"value":1143},{"type":22,"tag":852,"props":1944,"children":1945},{"class":854,"line":928},[1946,1950,1955,1960],{"type":22,"tag":852,"props":1947,"children":1948},{"style":874},[1949],{"type":28,"value":1432},{"type":22,"tag":852,"props":1951,"children":1952},{"style":868},[1953],{"type":28,"value":1954}," (AVPlayerItemStatusReadyToPlay ",{"type":22,"tag":852,"props":1956,"children":1957},{"style":874},[1958],{"type":28,"value":1959},"==",{"type":22,"tag":852,"props":1961,"children":1962},{"style":868},[1963],{"type":28,"value":1964}," _player.currentItem.status)\n",{"type":22,"tag":852,"props":1966,"children":1967},{"class":854,"line":957},[1968],{"type":22,"tag":852,"props":1969,"children":1970},{"style":868},[1971],{"type":28,"value":1446},{"type":22,"tag":852,"props":1973,"children":1974},{"class":854,"line":965},[1975],{"type":22,"tag":852,"props":1976,"children":1977},{"style":868},[1978],{"type":28,"value":1979},"         [_player play];\n",{"type":22,"tag":852,"props":1981,"children":1982},{"class":854,"line":974},[1983],{"type":22,"tag":852,"props":1984,"children":1985},{"style":868},[1986],{"type":28,"value":1479},{"type":22,"tag":852,"props":1988,"children":1989},{"class":854,"line":1059},[1990],{"type":22,"tag":852,"props":1991,"children":1992},{"style":868},[1993],{"type":28,"value":1609},{"type":22,"tag":852,"props":1995,"children":1996},{"class":854,"line":1096},[1997],{"type":22,"tag":852,"props":1998,"children":1999},{"style":868},[2000],{"type":28,"value":2001},"}\n",{"type":22,"tag":31,"props":2003,"children":2004},{},[2005],{"type":28,"value":2006},"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":22,"tag":31,"props":2008,"children":2009},{},[2010],{"type":22,"tag":791,"props":2011,"children":2012},{},[2013],{"type":28,"value":2014},"Slider Action",{"type":22,"tag":104,"props":2016,"children":2018},{"className":844,"code":2017,"language":846,"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",[2019],{"type":22,"tag":47,"props":2020,"children":2021},{"__ignoreMap":8},[2022,2030,2051,2058,2093,2100,2130,2165,2181],{"type":22,"tag":852,"props":2023,"children":2024},{"class":854,"line":855},[2025],{"type":22,"tag":852,"props":2026,"children":2027},{"style":859},[2028],{"type":28,"value":2029},"// Action for our 4 sliders\n",{"type":22,"tag":852,"props":2031,"children":2032},{"class":854,"line":258},[2033,2037,2042,2046],{"type":22,"tag":852,"props":2034,"children":2035},{"style":874},[2036],{"type":28,"value":1828},{"type":22,"tag":852,"props":2038,"children":2039},{"style":868},[2040],{"type":28,"value":2041}," (IBAction)mix",{"type":22,"tag":852,"props":2043,"children":2044},{"style":874},[2045],{"type":28,"value":914},{"type":22,"tag":852,"props":2047,"children":2048},{"style":868},[2049],{"type":28,"value":2050},"(id)sender\n",{"type":22,"tag":852,"props":2052,"children":2053},{"class":854,"line":255},[2054],{"type":22,"tag":852,"props":2055,"children":2056},{"style":868},[2057],{"type":28,"value":1904},{"type":22,"tag":852,"props":2059,"children":2060},{"class":854,"line":894},[2061,2066,2070,2075,2079,2084,2088],{"type":22,"tag":852,"props":2062,"children":2063},{"style":868},[2064],{"type":28,"value":2065},"   UISlider",{"type":22,"tag":852,"props":2067,"children":2068},{"style":874},[2069],{"type":28,"value":985},{"type":22,"tag":852,"props":2071,"children":2072},{"style":868},[2073],{"type":28,"value":2074}," slider ",{"type":22,"tag":852,"props":2076,"children":2077},{"style":874},[2078],{"type":28,"value":877},{"type":22,"tag":852,"props":2080,"children":2081},{"style":868},[2082],{"type":28,"value":2083}," (UISlider",{"type":22,"tag":852,"props":2085,"children":2086},{"style":874},[2087],{"type":28,"value":985},{"type":22,"tag":852,"props":2089,"children":2090},{"style":868},[2091],{"type":28,"value":2092},")sender;\n",{"type":22,"tag":852,"props":2094,"children":2095},{"class":854,"line":928},[2096],{"type":22,"tag":852,"props":2097,"children":2098},{"emptyLinePlaceholder":888},[2099],{"type":28,"value":891},{"type":22,"tag":852,"props":2101,"children":2102},{"class":854,"line":957},[2103,2108,2112,2116,2120,2125],{"type":22,"tag":852,"props":2104,"children":2105},{"style":868},[2106],{"type":28,"value":2107},"   [",{"type":22,"tag":852,"props":2109,"children":2110},{"style":917},[2111],{"type":28,"value":1572},{"type":22,"tag":852,"props":2113,"children":2114},{"style":868},[2115],{"type":28,"value":1577},{"type":22,"tag":852,"props":2117,"children":2118},{"style":874},[2119],{"type":28,"value":914},{"type":22,"tag":852,"props":2121,"children":2122},{"style":868},[2123],{"type":28,"value":2124},"slider.",{"type":22,"tag":852,"props":2126,"children":2127},{"style":917},[2128],{"type":28,"value":2129},"value\n",{"type":22,"tag":852,"props":2131,"children":2132},{"class":854,"line":965},[2133,2138,2142,2147,2151,2155,2160],{"type":22,"tag":852,"props":2134,"children":2135},{"style":868},[2136],{"type":28,"value":2137},"          forTrack",{"type":22,"tag":852,"props":2139,"children":2140},{"style":874},[2141],{"type":28,"value":914},{"type":22,"tag":852,"props":2143,"children":2144},{"style":868},[2145],{"type":28,"value":2146},"[NSString stringWithFormat",{"type":22,"tag":852,"props":2148,"children":2149},{"style":874},[2150],{"type":28,"value":914},{"type":22,"tag":852,"props":2152,"children":2153},{"style":868},[2154],{"type":28,"value":1008},{"type":22,"tag":852,"props":2156,"children":2157},{"style":1011},[2158],{"type":28,"value":2159},"\"track%d\"",{"type":22,"tag":852,"props":2161,"children":2162},{"style":868},[2163],{"type":28,"value":2164},", slider.tag]];\n",{"type":22,"tag":852,"props":2166,"children":2167},{"class":854,"line":974},[2168,2172,2176],{"type":22,"tag":852,"props":2169,"children":2170},{"style":868},[2171],{"type":28,"value":2107},{"type":22,"tag":852,"props":2173,"children":2174},{"style":917},[2175],{"type":28,"value":1572},{"type":22,"tag":852,"props":2177,"children":2178},{"style":868},[2179],{"type":28,"value":2180}," applyAudioMix];\n",{"type":22,"tag":852,"props":2182,"children":2183},{"class":854,"line":1059},[2184],{"type":22,"tag":852,"props":2185,"children":2186},{"style":868},[2187],{"type":28,"value":2001},{"type":22,"tag":31,"props":2189,"children":2190},{},[2191],{"type":28,"value":2192},"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":22,"tag":31,"props":2194,"children":2195},{},[2196],{"type":22,"tag":791,"props":2197,"children":2198},{},[2199],{"type":28,"value":2200},"Setting the Volume",{"type":22,"tag":104,"props":2202,"children":2204},{"className":844,"code":2203,"language":846,"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",[2205],{"type":22,"tag":47,"props":2206,"children":2207},{"__ignoreMap":8},[2208,2216,2255,2262,2297],{"type":22,"tag":852,"props":2209,"children":2210},{"class":854,"line":855},[2211],{"type":22,"tag":852,"props":2212,"children":2213},{"style":859},[2214],{"type":28,"value":2215},"// Set the volumne (0.0 - 1.0) for the given track\n",{"type":22,"tag":852,"props":2217,"children":2218},{"class":854,"line":258},[2219,2223,2228,2232,2237,2241,2246,2250],{"type":22,"tag":852,"props":2220,"children":2221},{"style":874},[2222],{"type":28,"value":1828},{"type":22,"tag":852,"props":2224,"children":2225},{"style":868},[2226],{"type":28,"value":2227}," (void)setVolume",{"type":22,"tag":852,"props":2229,"children":2230},{"style":874},[2231],{"type":28,"value":914},{"type":22,"tag":852,"props":2233,"children":2234},{"style":868},[2235],{"type":28,"value":2236},"(float)volume forTrack",{"type":22,"tag":852,"props":2238,"children":2239},{"style":874},[2240],{"type":28,"value":914},{"type":22,"tag":852,"props":2242,"children":2243},{"style":868},[2244],{"type":28,"value":2245},"(NSString",{"type":22,"tag":852,"props":2247,"children":2248},{"style":874},[2249],{"type":28,"value":985},{"type":22,"tag":852,"props":2251,"children":2252},{"style":868},[2253],{"type":28,"value":2254},")audioTrackName\n",{"type":22,"tag":852,"props":2256,"children":2257},{"class":854,"line":255},[2258],{"type":22,"tag":852,"props":2259,"children":2260},{"style":868},[2261],{"type":28,"value":1904},{"type":22,"tag":852,"props":2263,"children":2264},{"class":854,"line":894},[2265,2270,2274,2279,2283,2288,2292],{"type":22,"tag":852,"props":2266,"children":2267},{"style":868},[2268],{"type":28,"value":2269},"   [_audioMixValues setValue",{"type":22,"tag":852,"props":2271,"children":2272},{"style":874},[2273],{"type":28,"value":914},{"type":22,"tag":852,"props":2275,"children":2276},{"style":868},[2277],{"type":28,"value":2278},"[NSNumber numberWithFloat",{"type":22,"tag":852,"props":2280,"children":2281},{"style":874},[2282],{"type":28,"value":914},{"type":22,"tag":852,"props":2284,"children":2285},{"style":868},[2286],{"type":28,"value":2287},"volume] forKey",{"type":22,"tag":852,"props":2289,"children":2290},{"style":874},[2291],{"type":28,"value":914},{"type":22,"tag":852,"props":2293,"children":2294},{"style":868},[2295],{"type":28,"value":2296},"audioTrackName];\n",{"type":22,"tag":852,"props":2298,"children":2299},{"class":854,"line":928},[2300],{"type":22,"tag":852,"props":2301,"children":2302},{"style":868},[2303],{"type":28,"value":2001},{"type":22,"tag":31,"props":2305,"children":2306},{},[2307],{"type":28,"value":2308},"When we set the volume we simply update the value in our NSMutableDictionary that stores the volume level for each track.",{"type":22,"tag":31,"props":2310,"children":2311},{},[2312],{"type":22,"tag":791,"props":2313,"children":2314},{},[2315],{"type":28,"value":2316},"Applying the Mix",{"type":22,"tag":104,"props":2318,"children":2320},{"className":844,"code":2319,"language":846,"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",[2321],{"type":22,"tag":47,"props":2322,"children":2323},{"__ignoreMap":8},[2324,2332,2344,2351,2377,2384,2422,2429,2456,2509,2516,2551,2558,2584,2601,2608,2625,2633,2640,2657,2664,2681],{"type":22,"tag":852,"props":2325,"children":2326},{"class":854,"line":855},[2327],{"type":22,"tag":852,"props":2328,"children":2329},{"style":859},[2330],{"type":28,"value":2331},"// Build and apply an audio mix using our volume values\n",{"type":22,"tag":852,"props":2333,"children":2334},{"class":854,"line":258},[2335,2339],{"type":22,"tag":852,"props":2336,"children":2337},{"style":874},[2338],{"type":28,"value":1828},{"type":22,"tag":852,"props":2340,"children":2341},{"style":868},[2342],{"type":28,"value":2343}," (void)applyAudioMix\n",{"type":22,"tag":852,"props":2345,"children":2346},{"class":854,"line":255},[2347],{"type":22,"tag":852,"props":2348,"children":2349},{"style":868},[2350],{"type":28,"value":1904},{"type":22,"tag":852,"props":2352,"children":2353},{"class":854,"line":894},[2354,2359,2363,2368,2372],{"type":22,"tag":852,"props":2355,"children":2356},{"style":868},[2357],{"type":28,"value":2358},"   AVMutableAudioMix",{"type":22,"tag":852,"props":2360,"children":2361},{"style":874},[2362],{"type":28,"value":985},{"type":22,"tag":852,"props":2364,"children":2365},{"style":868},[2366],{"type":28,"value":2367}," mix ",{"type":22,"tag":852,"props":2369,"children":2370},{"style":874},[2371],{"type":28,"value":877},{"type":22,"tag":852,"props":2373,"children":2374},{"style":868},[2375],{"type":28,"value":2376}," [AVMutableAudioMix audioMix];\n",{"type":22,"tag":852,"props":2378,"children":2379},{"class":854,"line":928},[2380],{"type":22,"tag":852,"props":2381,"children":2382},{"emptyLinePlaceholder":888},[2383],{"type":28,"value":891},{"type":22,"tag":852,"props":2385,"children":2386},{"class":854,"line":957},[2387,2392,2396,2401,2405,2410,2414,2418],{"type":22,"tag":852,"props":2388,"children":2389},{"style":868},[2390],{"type":28,"value":2391},"   NSMutableArray",{"type":22,"tag":852,"props":2393,"children":2394},{"style":874},[2395],{"type":28,"value":985},{"type":22,"tag":852,"props":2397,"children":2398},{"style":868},[2399],{"type":28,"value":2400}," inputParameters ",{"type":22,"tag":852,"props":2402,"children":2403},{"style":874},[2404],{"type":28,"value":877},{"type":22,"tag":852,"props":2406,"children":2407},{"style":868},[2408],{"type":28,"value":2409}," [[NSMutableArray alloc] initWithCapacity",{"type":22,"tag":852,"props":2411,"children":2412},{"style":874},[2413],{"type":28,"value":914},{"type":22,"tag":852,"props":2415,"children":2416},{"style":917},[2417],{"type":28,"value":920},{"type":22,"tag":852,"props":2419,"children":2420},{"style":868},[2421],{"type":28,"value":925},{"type":22,"tag":852,"props":2423,"children":2424},{"class":854,"line":965},[2425],{"type":22,"tag":852,"props":2426,"children":2427},{"emptyLinePlaceholder":888},[2428],{"type":28,"value":891},{"type":22,"tag":852,"props":2430,"children":2431},{"class":854,"line":974},[2432,2437,2442,2447,2451],{"type":22,"tag":852,"props":2433,"children":2434},{"style":868},[2435],{"type":28,"value":2436},"   [_audioMixTrackIDs enumerateKeysAndObjectsUsingBlock",{"type":22,"tag":852,"props":2438,"children":2439},{"style":874},[2440],{"type":28,"value":2441},":^",{"type":22,"tag":852,"props":2443,"children":2444},{"style":868},[2445],{"type":28,"value":2446},"(id key, id obj, BOOL",{"type":22,"tag":852,"props":2448,"children":2449},{"style":874},[2450],{"type":28,"value":985},{"type":22,"tag":852,"props":2452,"children":2453},{"style":868},[2454],{"type":28,"value":2455},"stop) {\n",{"type":22,"tag":852,"props":2457,"children":2458},{"class":854,"line":1059},[2459,2464,2468,2473,2477,2482,2486,2491,2495,2500,2504],{"type":22,"tag":852,"props":2460,"children":2461},{"style":868},[2462],{"type":28,"value":2463},"      AVAssetTrack",{"type":22,"tag":852,"props":2465,"children":2466},{"style":874},[2467],{"type":28,"value":985},{"type":22,"tag":852,"props":2469,"children":2470},{"style":868},[2471],{"type":28,"value":2472}," track ",{"type":22,"tag":852,"props":2474,"children":2475},{"style":874},[2476],{"type":28,"value":877},{"type":22,"tag":852,"props":2478,"children":2479},{"style":868},[2480],{"type":28,"value":2481}," [",{"type":22,"tag":852,"props":2483,"children":2484},{"style":917},[2485],{"type":28,"value":1572},{"type":22,"tag":852,"props":2487,"children":2488},{"style":868},[2489],{"type":28,"value":2490}," trackWithId",{"type":22,"tag":852,"props":2492,"children":2493},{"style":874},[2494],{"type":28,"value":914},{"type":22,"tag":852,"props":2496,"children":2497},{"style":868},[2498],{"type":28,"value":2499},"(CMPersistentTrackID)[(NSNumber",{"type":22,"tag":852,"props":2501,"children":2502},{"style":874},[2503],{"type":28,"value":985},{"type":22,"tag":852,"props":2505,"children":2506},{"style":868},[2507],{"type":28,"value":2508},")obj integerValue]];\n",{"type":22,"tag":852,"props":2510,"children":2511},{"class":854,"line":1096},[2512],{"type":22,"tag":852,"props":2513,"children":2514},{"emptyLinePlaceholder":888},[2515],{"type":28,"value":891},{"type":22,"tag":852,"props":2517,"children":2518},{"class":854,"line":1104},[2519,2524,2528,2533,2537,2542,2546],{"type":22,"tag":852,"props":2520,"children":2521},{"style":868},[2522],{"type":28,"value":2523},"      AVMutableAudioMixInputParameters",{"type":22,"tag":852,"props":2525,"children":2526},{"style":874},[2527],{"type":28,"value":985},{"type":22,"tag":852,"props":2529,"children":2530},{"style":868},[2531],{"type":28,"value":2532}," params ",{"type":22,"tag":852,"props":2534,"children":2535},{"style":874},[2536],{"type":28,"value":877},{"type":22,"tag":852,"props":2538,"children":2539},{"style":868},[2540],{"type":28,"value":2541}," [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack",{"type":22,"tag":852,"props":2543,"children":2544},{"style":874},[2545],{"type":28,"value":914},{"type":22,"tag":852,"props":2547,"children":2548},{"style":868},[2549],{"type":28,"value":2550},"track];\n",{"type":22,"tag":852,"props":2552,"children":2553},{"class":854,"line":1137},[2554],{"type":22,"tag":852,"props":2555,"children":2556},{"emptyLinePlaceholder":888},[2557],{"type":28,"value":891},{"type":22,"tag":852,"props":2559,"children":2560},{"class":854,"line":1146},[2561,2566,2570,2575,2579],{"type":22,"tag":852,"props":2562,"children":2563},{"style":868},[2564],{"type":28,"value":2565},"      [params setVolume",{"type":22,"tag":852,"props":2567,"children":2568},{"style":874},[2569],{"type":28,"value":914},{"type":22,"tag":852,"props":2571,"children":2572},{"style":868},[2573],{"type":28,"value":2574},"[[_audioMixValues valueForKey",{"type":22,"tag":852,"props":2576,"children":2577},{"style":874},[2578],{"type":28,"value":914},{"type":22,"tag":852,"props":2580,"children":2581},{"style":868},[2582],{"type":28,"value":2583},"key] floatValue]\n",{"type":22,"tag":852,"props":2585,"children":2586},{"class":854,"line":1209},[2587,2592,2596],{"type":22,"tag":852,"props":2588,"children":2589},{"style":868},[2590],{"type":28,"value":2591},"                 atTime",{"type":22,"tag":852,"props":2593,"children":2594},{"style":874},[2595],{"type":28,"value":914},{"type":22,"tag":852,"props":2597,"children":2598},{"style":868},[2599],{"type":28,"value":2600},"kCMTimeZero];\n",{"type":22,"tag":852,"props":2602,"children":2603},{"class":854,"line":1230},[2604],{"type":22,"tag":852,"props":2605,"children":2606},{"emptyLinePlaceholder":888},[2607],{"type":28,"value":891},{"type":22,"tag":852,"props":2609,"children":2610},{"class":854,"line":1238},[2611,2616,2620],{"type":22,"tag":852,"props":2612,"children":2613},{"style":868},[2614],{"type":28,"value":2615},"      [inputParameters addObject",{"type":22,"tag":852,"props":2617,"children":2618},{"style":874},[2619],{"type":28,"value":914},{"type":22,"tag":852,"props":2621,"children":2622},{"style":868},[2623],{"type":28,"value":2624},"params];\n",{"type":22,"tag":852,"props":2626,"children":2627},{"class":854,"line":1274},[2628],{"type":22,"tag":852,"props":2629,"children":2630},{"style":868},[2631],{"type":28,"value":2632},"   }];\n",{"type":22,"tag":852,"props":2634,"children":2635},{"class":854,"line":1292},[2636],{"type":22,"tag":852,"props":2637,"children":2638},{"emptyLinePlaceholder":888},[2639],{"type":28,"value":891},{"type":22,"tag":852,"props":2641,"children":2642},{"class":854,"line":1300},[2643,2648,2652],{"type":22,"tag":852,"props":2644,"children":2645},{"style":868},[2646],{"type":28,"value":2647},"   mix.inputParameters ",{"type":22,"tag":852,"props":2649,"children":2650},{"style":874},[2651],{"type":28,"value":877},{"type":22,"tag":852,"props":2653,"children":2654},{"style":868},[2655],{"type":28,"value":2656}," inputParameters;\n",{"type":22,"tag":852,"props":2658,"children":2659},{"class":854,"line":1318},[2660],{"type":22,"tag":852,"props":2661,"children":2662},{"emptyLinePlaceholder":888},[2663],{"type":28,"value":891},{"type":22,"tag":852,"props":2665,"children":2666},{"class":854,"line":1341},[2667,2672,2676],{"type":22,"tag":852,"props":2668,"children":2669},{"style":868},[2670],{"type":28,"value":2671},"   _player.currentItem.audioMix ",{"type":22,"tag":852,"props":2673,"children":2674},{"style":874},[2675],{"type":28,"value":877},{"type":22,"tag":852,"props":2677,"children":2678},{"style":868},[2679],{"type":28,"value":2680}," mix;\n",{"type":22,"tag":852,"props":2682,"children":2683},{"class":854,"line":1381},[2684],{"type":22,"tag":852,"props":2685,"children":2686},{"style":868},[2687],{"type":28,"value":2001},{"type":22,"tag":31,"props":2689,"children":2690},{},[2691,2693,2700,2702,2709],{"type":28,"value":2692},"Here's where we update and apply the audio mix to our composition. First we create an instance of the ",{"type":22,"tag":64,"props":2694,"children":2697},{"href":2695,"rel":2696},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableAudioMix_Class/Reference/Reference.html",[68],[2698],{"type":28,"value":2699},"AVMutableAudioMix",{"type":28,"value":2701}," class and then for each track create an ",{"type":22,"tag":64,"props":2703,"children":2706},{"href":2704,"rel":2705},"https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVMutableAudioMixInputParameters_Class/Reference/Reference.html",[68],[2707],{"type":28,"value":2708},"AVMutableAudioMixInputParameters",{"type":28,"value":2710}," 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":22,"tag":31,"props":2712,"children":2713},{},[2714],{"type":22,"tag":791,"props":2715,"children":2716},{},[2717],{"type":28,"value":2718},"Closing Thoughts",{"type":22,"tag":31,"props":2720,"children":2721},{},[2722],{"type":28,"value":2723},"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":22,"tag":31,"props":2725,"children":2726},{},[2727],{"type":28,"value":2728},"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":22,"tag":2730,"props":2731,"children":2732},"style",{},[2733],{"type":28,"value":2734},"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":255,"depth":255,"links":2736},[],"content:shuey:2012-07:mixer.md","shuey/2012-07/mixer.md","shuey/2012-07/mixer",{"user":729,"name":730},{"_path":2742,"_dir":2743,"_draft":7,"_partial":7,"_locale":8,"title":2744,"description":2745,"publishDate":2746,"tags":2747,"image":2748,"excerpt":2745,"body":2749,"_type":262,"_id":2795,"_source":264,"_file":2796,"_stem":2797,"_extension":267,"author":2798},"/shuey/2012-06/thoughts-ios6","2012-06","A few thoughts on iOS 6","Apple made their session videos from WWDC 2012 available earlier this week in record time. It's nice to see since tickets for this years event sold out in under two hours. Apple has an iOS 6 Preview page touting some of the new features such as Siri's new abilities, tighter integration with Facebook, Photo Stream sharing, and things like iCloud tabs for Safari all of which look great.","2012-06-21",[15,279],"/shuey/2012-06/img/ios6.jpg",{"type":19,"children":2750,"toc":2793},[2751,2774,2779],{"type":22,"tag":31,"props":2752,"children":2753},{},[2754,2756,2763,2765,2772],{"type":28,"value":2755},"Apple made their ",{"type":22,"tag":64,"props":2757,"children":2760},{"href":2758,"rel":2759},"https://developer.apple.com/videos/wwdc/2012/",[68],[2761],{"type":28,"value":2762},"session videos from WWDC 2012 available",{"type":28,"value":2764}," earlier this week in record time. It's nice to see since tickets for this years event sold out in under two hours. Apple has an ",{"type":22,"tag":64,"props":2766,"children":2769},{"href":2767,"rel":2768},"http://www.apple.com/ios/ios6/",[68],[2770],{"type":28,"value":2771},"iOS 6 Preview",{"type":28,"value":2773}," page touting some of the new features such as Siri's new abilities, tighter integration with Facebook, Photo Stream sharing, and things like iCloud tabs for Safari all of which look great.",{"type":22,"tag":31,"props":2775,"children":2776},{},[2777],{"type":28,"value":2778},"What stands out most about iOS 6 to me are the changes Apple has made to the OS to compete in the mobile arena. The all new Maps app that uses their own data instead of Google's, the Safari search field now reads \"Search\" instead of \"Google\", the OS level integration with Facebook (to go along with Twitter), features catering to the expanding Chinese market, and increased use of iCloud.",{"type":22,"tag":31,"props":2780,"children":2781},{},[2782,2784,2791],{"type":28,"value":2783},"Apple took some shots at Android and Samsung during the keynote but looks to take an even larger one when iOS 6 is released this fall, likely alongside the release of the next iPhone. If the adoption rates for iOS 6 are similar to iOS 5 (which are huge compared to ",{"type":22,"tag":64,"props":2785,"children":2788},{"href":2786,"rel":2787},"http://www.android.com",[68],[2789],{"type":28,"value":2790},"Android's 4.0 Ice Cream Sandwich",{"type":28,"value":2792}," release) and if the next iPhone sells anything close to how the 4S is, it will be interesting to see how market shares and revenues turn out late this year for the two companies.",{"title":8,"searchDepth":255,"depth":255,"links":2794},[],"content:shuey:2012-06:thoughts-ios6.md","shuey/2012-06/thoughts-ios6.md","shuey/2012-06/thoughts-ios6",{"user":729,"name":730},{"_path":2800,"_dir":2801,"_draft":7,"_partial":7,"_locale":8,"title":2802,"description":2803,"publishDate":2804,"tags":2805,"image":2807,"excerpt":2803,"body":2808,"_type":262,"_id":2849,"_source":264,"_file":2850,"_stem":2851,"_extension":267,"author":2852},"/shuey/2012-05/cloud","2012-05","Under the Sheets with iCloud and Core Data","Drew McCormack is writing a great series (Part 1, Part 2, Part 3) of posts about using iCloud for syncing Core Data managed data. It's harder than Apple lets on and Drew has done a great job of uncovering how this actually works.","2012-05-28",[15,2806],"icloud","/shuey/2012-05/img/icloud.jpg",{"type":19,"children":2809,"toc":2847},[2810],{"type":22,"tag":31,"props":2811,"children":2812},{},[2813,2820,2822,2829,2830,2837,2838,2845],{"type":22,"tag":64,"props":2814,"children":2818},{"href":2815,"rel":2816,"title":2817},"https://twitter.com/#!/drewmccormack",[68],"Drew McCormack",[2819],{"type":28,"value":2817},{"type":28,"value":2821}," is writing a great series (",{"type":22,"tag":64,"props":2823,"children":2826},{"href":2824,"rel":2825},"http://mentalfaculty.tumblr.com/post/23163747823/under-the-sheets-with-icloud-and-core-data-the-basics",[68],[2827],{"type":28,"value":2828},"Part 1",{"type":28,"value":1047},{"type":22,"tag":64,"props":2831,"children":2834},{"href":2832,"rel":2833},"http://mentalfaculty.tumblr.com/post/23231176783/under-the-sheets-with-icloud-and-core-data-how-it",[68],[2835],{"type":28,"value":2836},"Part 2",{"type":28,"value":1047},{"type":22,"tag":64,"props":2839,"children":2842},{"href":2840,"rel":2841},"http://mentalfaculty.tumblr.com/post/23788055417/under-the-sheets-with-icloud-and-core-data-seeding",[68],[2843],{"type":28,"value":2844},"Part 3",{"type":28,"value":2846},") of posts about using iCloud for syncing Core Data managed data. It's harder than Apple lets on and Drew has done a great job of uncovering how this actually works.",{"title":8,"searchDepth":255,"depth":255,"links":2848},[],"content:shuey:2012-05:cloud.md","shuey/2012-05/cloud.md","shuey/2012-05/cloud",{"user":729,"name":730},1780330267146]