<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[FightNome Dev Notes]]></title><description><![CDATA[FightNome Dev Notes]]></description><link>https://fightnome.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 11:22:22 GMT</lastBuildDate><atom:link href="https://fightnome.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[One backing track, many tempos: the numbers behind stretching a 90 BPM bed from 74 to 128 BPM]]></title><description><![CDATA[I build FightNome, a boxing and Muay Thai training app, and this note comes from working on its audio. In FightNome a recorded coach calls strikes on the…]]></description><link>https://fightnome.hashnode.dev/one-backing-track-many-tempos-the-numbers-behind-stretching-a-90-bpm-bed-from-74-to-128-bpm</link><guid isPermaLink="true">https://fightnome.hashnode.dev/one-backing-track-many-tempos-the-numbers-behind-stretching-a-90-bpm-bed-from-74-to-128-bpm</guid><category><![CDATA[Mobile Development]]></category><category><![CDATA[audio]]></category><category><![CDATA[iOS]]></category><category><![CDATA[music]]></category><dc:creator><![CDATA[FightNome]]></dc:creator><pubDate>Thu, 05 Nov 2026 14:12:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ae094855de8d41ceccfa25f/a375b92a-0ebf-4ff0-a627-87bf7f3aac2a.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>I build FightNome, a boxing and Muay Thai training app, and this note comes from working on its audio.</em></p>
<p>In FightNome a recorded coach calls strikes on the beat of a backing track. There's one track, "Back From Zero", recorded at 90 BPM. Workout sections can run anywhere from 74 to 128 BPM, so that same track gets time-stretched to whatever tempo the section uses. Writing down the numbers helped me see where the tricky parts are, so here they are.</p>
<h2>How far the track gets stretched</h2>
<p>The stretch factor is just the target tempo divided by the native tempo:</p>
<table>
<thead>
<tr>
<th>Section tempo</th>
<th>Factor vs 90 BPM</th>
<th>One beat</th>
</tr>
</thead>
<tbody><tr>
<td>74 BPM</td>
<td>0.82x (about 18% slower)</td>
<td>811 ms</td>
</tr>
<tr>
<td>90 BPM</td>
<td>1.00x</td>
<td>667 ms</td>
</tr>
<tr>
<td>128 BPM</td>
<td>1.42x (about 42% faster)</td>
<td>469 ms</td>
</tr>
</tbody></table>
<p>One beat is 60000 / BPM milliseconds. The default for workouts is 90 BPM, which the app describes as a pace built for clean technique, so most sessions play the track as recorded.</p>
<p>The range isn't symmetric. Going down to 74 only slows the track by under a fifth, while going up to 128 speeds it up by more than two fifths. If something sounds wrong, it's more likely to show up at the fast end.</p>
<h2>Why the track and the voice are handled differently</h2>
<p>The music bed can be stretched because nobody is listening for exact timbre in it. The coach's voice is different. Every callout is its own recorded file, one word per file, and each one starts 40 to 60 ms before its beat so the word seems to land on the tick. A spoken word that's been sped up 42% stops sounding like the same person. Because each word is a separate file placed on the beat grid, the voice doesn't have to go through the same stretch as the music.</p>
<p>That means the gap between words shrinks as the tempo goes up. At 128 BPM a beat is 469 ms, and a two-syllable callout like "upper" has to fit inside it before the next call starts. At 74 BPM there's plenty of room. Picking the word list per strike (short words like "jab", "hook", "two") does part of the job here.</p>
<h2>Half time and double time</h2>
<p>Each section also has an intensity setting: half time, normal time or double time. Double time at the top of the tempo range is the setting I'd test hardest, because that's where the spacing question above gets tightest.</p>
<h2>What I'd check if you're doing something similar</h2>
<ul>
<li>Work out the extreme ratios first, because the edges are where it breaks.</li>
<li>Listen to the fastest setting on cheap earbuds, since that's how most people will hear it.</li>
<li>Keep speech out of the stretch path if you can, and align it by start time instead.</li>
<li>Measure the head start for each word, since a word with a soft first consonant may need to start earlier to feel on the beat.</li>
</ul>
<p>If you've stretched music in an app over a wider range than this, I'd like to know at what ratio it started sounding wrong for you.</p>
<p><em>I used AI assistance to draft this note and edited it myself.</em></p>
]]></content:encoded></item><item><title><![CDATA[Testing AlarmKit alarms in the iOS 26 Simulator: what you can and can't capture]]></title><description><![CDATA[I build FightNome, a boxing and Muay Thai training app, and this note comes from adding alarms to it. We added workout alarms in iOS 26 with AlarmKit. You…]]></description><link>https://fightnome.hashnode.dev/testing-alarmkit-alarms-in-the-ios-26-simulator-what-you-can-and-can-t-capture</link><guid isPermaLink="true">https://fightnome.hashnode.dev/testing-alarmkit-alarms-in-the-ios-26-simulator-what-you-can-and-can-t-capture</guid><category><![CDATA[Testing]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Swift]]></category><dc:creator><![CDATA[FightNome]]></dc:creator><pubDate>Fri, 30 Oct 2026 14:10:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ae094855de8d41ceccfa25f/8de2c57b-fcf8-4ffe-9c20-df33ecf8466e.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>I build FightNome, a boxing and Muay Thai training app, and this note comes from adding alarms to it.</em></p>
<p>We added workout alarms in iOS 26 with AlarmKit. You set an alarm on a workout with a time and days, and at that time the phone rings with a short recorded coach line such as "Time to work. Gloves on." There's a button that starts the workout straight from the alarm. Before shipping, I wanted video of the whole thing for the store page, and I wanted to check it in the Simulator first. A few things surprised me.</p>
<h2>The permission text tells you what the alarm can do</h2>
<p>AlarmKit's system permission text says the alarms "appear on screen even if a Focus is active". That's the reason to use it for this case instead of a normal notification. The caption we put next to the toggle says the same thing in our words: it breaks silent mode, and one tap starts the session.</p>
<h2>It fires as a Live Activity</h2>
<p>In the iOS 26.4 Simulator, an alarm set for 05:00 fired on time and showed up as a Live Activity, with the workout name in the Dynamic Island. So far so good.</p>
<h2>Recording is where it gets odd</h2>
<ul>
<li>With the Simulator locked, <code>simctl io</code> screenshots and recordings showed nothing of the alarm at all.</li>
<li>Unlocked on the home screen, the captures showed the red alarm glyph in the Dynamic Island, but the expanded view came out black.</li>
<li>No sound reached any process I tapped. The only way I got the alarm's audio into a cut was to use the alarm's own WAV file in the edit.</li>
</ul>
<p>None of this means the feature is broken. It just means the Simulator is a poor place to film it.</p>
<h2>What I'd do next time</h2>
<p>Treat the Simulator as a check that the alarm is scheduled and fires at the right time, and nothing more. For anything you want to show people, ring it on a real iPhone and film the device with a second camera, since a full ring with sound is easiest to capture that way.</p>
<p>If you've found a clean way to record AlarmKit alerts with sound from the Simulator, I'd be glad to hear it.</p>
<p><em>I used AI assistance to draft this note and edited it myself.</em></p>
]]></content:encoded></item></channel></rss>