Adding Smart Speed to any audio file with Audacity

The Overcast podcast app by Marco Arment has a killer feature called Smart Speed and it has ruined all audio listening for me outside of the app. Smart Speed dynamically shortens silences in talk shows; it saves you time, and makes them feel tighter and more produced. I wish I had it everywhere.

Tekside is a podcast network I'm part of, and while some of our shows are heavily edited, many are not. While doing some audio work for something else, my wife noticed that Audacity (cross platform) has a crud version of this type of audio processing. Here's how to set it up.

Setup

  1. Download Audacity & install it. But don't run it yet. (If it opened as part of install, close it)
  2. If you are working with audio files already, head to "Making it work". If you are pulling in .mov files from Skype Call Recorder see step 3
  3. Install FFMPEG: If you are on a Mac, download and install this Otherwise, see these instructions

Making it work

  1. Open Audacity
  2. Click File -> Import Audio
  3. Choose your audio recording
  4. Optional: If Audacity prompts you to "Select Stream(s) to import", select all of them and hit OK
  5. Select one of the audio streams and hit CMD+A to highlight all of the audio
  6. Click Effect -> Truncate Silence
  7. I currently have duration set to 0.9 and truncate to set to 0.5. What this does is find any silence longer that 0.9 seconds and shorten it to 0.5 seconds
  8. Hit ok & let it run
  9. File -> Export (As a WAV. You may have to hit OK a few times)
  10. Done!

I'm still figuring out which duration will work best for which shows. It depends how fast the people on it already naturally talk and flow which each other. For Show and Tell, our movie podcast, the above settings strip a 55 min recording to 48 mins and it sounds a lot tighter.

Using an Encrypted Realm in a background or notification processes?

Note: This post's primary purpose is to help me think through this problem. I have no prescribed solution at the end of it. The conversation will continue on Stack Overflow. I will update this post once I have a final approach.

Realm has a great write up and sample code for encrypting your database. This documentation and sample work as intended, until you try to decrypt realm when:

  1. A user has a password on their phone
  2. The device is locked
  3. Your app is trying to do work with Realm when a remote notification comes in

This happens because we can't access the keychain to get (or create) the key to en/decrypt the Realm. The default kSecAttrAccessible value is kSecAttrAccessibleWhenUnlocked

There are a few options as I see them:

  1. Change kSecAttrAccessible to kSecAttrAccessibleAlways. I don't like this because it's a) too open and b) it was slated to be deprecated in iOS 9
  2. Change kSecAttrAccessible to kSecAttrAccessibleAfterFirstUnlock or kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly. This is better but still feels too open to me, even though the docs state: This is recommended for items that need to be accessed by background applications
  3. Create a second, non-encrypted Realm to use as a staging database. Store notification data here, then when the app wakes up from user interaction (the device would be unlocked), move the data from the staging Realm into the encrypted real one. This doesn't feel right either, as we'll have data temporarily not encrypted
  4. Combine 2 and 3 and encrypt the staging Realm, and protect it's key with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
  5. ??

I'm currently trying to decide if #2, if #3 is worth putting the time into, or if I can come up with a #5

Using iOS 10 devices with Xcode 7

Peter Steinberger started a GREAT gist on Using Xcode 7.3.1 and iOS 10 devices.

Below is what worked for me to get a few extra test devices (my carry phone runs the 10 beta) working with Xcode 7. Can't upgrade to 8 just yet. Working with a contractor and don't want to move too many pieces.

My Setup

Xcode 7.3.1 and Beta 6 iOS 10 beta 6 (Beta 7 is out, after getting this to work, I don't think I'm upgrading just yet)

Steps

  1. sudo ln -s /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.0\ \(14A5339a\)/ /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
  2. iPhone: Settings > General > Reset > Network Settings
  3. Reboot iPhone (after it wakes back up from the network reset)
  4. Reboot Mac (restarting Xcode alone didn't work)

It these steps don't work for you, check out the gist for other options.

Opening iTerm2 Tabs at Specific Directories

I love iTerm2. I can customize the stock Terminal.app just about as much, but it's much easier in iTerm. I find myself always opening the same 3 or 4 tabs when I get into coding mode. Luckily iTerm2 has great scripting support

The 4 tabs I always open for Kidfund are:

  1. Our iOS project
  2. Our Laravel project. Usually where I run artisan commands
  3. Our Laravel project; Tails most recent file in the log directory
  4. Our Laravel project; I jump around from here. Usually CD-ing to 1. the realm directory to pop it into Realm Browser

I didn't want this to run all of the time so I didn't have this script run each time iTerm opens. I instead wired it into an Alfred command. If you are interested you can download that here

The underlying script is as follows. It's crud, and could definitely be more flexible, but it works for me at the moment. Hopefully it can help you craft something to your needs

tell application "iTerm2"
  tell current session of current window
    write text "cd ~/workspace/kidfund/ios"
  end tell
  tell current window
    create tab with default profile
      tell current session of current tab
        write text "cd ~/workspace/kidfund/web"
      end tell
  end tell
    tell current window
    create tab with default profile
      tell current session of current tab
        write text "cd ~/workspace/kidfund/web && tail -f storage/logs/\"$(ls -at storage/logs | head -n 1)\""
      end tell
  end tell
    tell current window
    create tab with default profile
      tell current session of current tab
        write text "cd ~/workspace/kidfund/web"
      end tell
  end tell
end tell

Github File and Link Tricks

2 tricks I learned today that I'd like to share: reliably linking to a specific line and searching for files using fuzzy matching.

Reliably link to a specific line

Say you are on the master branch, and you want to reference a line in a file. This could either be for a conversation you are having at that moment, answering a question in a PR, or adding information to a ticket. At that point in time, your link will work great. But, what about when that file gets changed tomorrow? More lines get added higher up, above the link, and the line that the link it pointing to, now points to something else!

You can easily have github switch to the latest commit for the file you are viewing. Just press 'y'. Then, when you link to a line, you are linking to THAT version of the file. You reference will always be intact.

Search for files using fuzzy matching

When you are browsing through files, there is a button in the upper right that says "Find file". I'm sure it's been there forever, but I just noticed it.

This brings you to a full file tree that you can search using fuzzy matching. Just like if you were in your IDE quick-opening a file!

Setup and Teardown the Database Once Per Test Suite in PHPUnit

I'm working on a series of integration tests where I want to set up and reset the database for each run. This could easily be done in the setUp and tearDown methods, but doing the full db each time is slow. Yes, I could just do the tables I need, but I was curious, and now I don't have to worry about which tables are setup in my testing DB. In this example, I'm using Laravel's migrations and SQLite as the test DB.

UPDATE 05/05/2016: As Sebastian points out below (thanks!) there is a much more appropriate way. Using setUpBeforeClass and tearDownAfterClass we achieve the same effect

public static function setUpBeforeClass()
{
    parent::setUpBeforeClass();
    exec('php artisan migrate --database sqlite_test');
}

public static function tearDownAfterClass()
{
    exec('php artisan migrate:reset --database sqlite_test');
    parent::tearDownAfterClass(); 
}

PHPUnit has listeners that you can tap into at various parts of your tests' lifecycle. I'm particularly interested in when a specific suite starts and ends. We'll need to do 2 things:

  1. Create our Listener
  2. Register this Listener in phpunit.xml

The listener is as follows:

class FullDBListener extends PHPUnit_Framework_BaseTestListener
{
    protected $suites = ['UserIntegrationTest', 'AccountIntegrationTest'];

    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if (in_array($suite->getName(), $this->suites)) {
            exec('php artisan migrate --database sqlite_test');
        }
    }

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if (in_array($suite->getName(), $this->suites)) {
            exec('php artisan migrate:reset --database sqlite_test');
        }
    }
}

This does a few things:

  1. Stores the class names of each suite we want to run the db migrations for
  2. In startTestSuite it checks to see if we're in the right suite
  3. If we are, run an artisan migration on our test db
  4. In endTestSuite it checks to see if we're in the right suite
  5. If we are, run an artisan migration:reset on our test db

Next, we need to make PHPUnit aware of this listener. Update your path accordingly

<listeners>
    <listener class="FullDBListener" file="./tests/app/FullDBListener.php"></listener>
</listeners>

That's it!

I do do some basic teardown in my test suite's setUp method to give me a blank slate. This has proven faster then doing the migrations each time

public function setUp()
{
    parent::setUp();

    User::truncate();
}

I hope this helped you, if you have any questions, let me know!

Trying to Mock a Self Booting Laravel Model Trait

Bootable Model traits are pretty nifty. I'm using them to register certain events for the models using my Trait. However, I've run into an issue trying to mock models that are using the trait. Specifically, when a Mockery version of the model is instantiated, it's boot code agrees that it should have a bootMyTrait method, but can't find it when it tries to call it.

Sample Repository for the below, with commands to reproduce.

As an example, here is a trait:

namespace App;
trait MyTrait
{
    public static function bootMyTrait()
    {
        print("Booting MyTrait\n");
    }
}

And a model using it:

namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
    use MyTrait;
}

Instantiating the model regularly works fine. This shows the desired output:

$model = new MyModel();

However, trying to mock this model does not cooperate. This:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;


class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $model = $this->getMock('App\MyModel');
    }
}

Fails. Adding some debugging to Eloquent:

    /**
     * Boot all of the bootable traits on the model.
     *
     * @return void
     */
    protected static function bootTraits()
    {
        $class = static::class;

        foreach (class_uses_recursive($class) as $trait) {
            print("\nTesting that class: $class has method: " . $method = 'boot'.class_basename($trait) . " because of Trait: $trait\n");
            if (method_exists($class, $method = 'boot'.class_basename($trait))) {
                print("Class: $class has method: $method \n");
                try {
                    forward_static_call([$class, $method]);
                } catch (\PHPUnit_Framework_MockObject_BadMethodCallException $e) {
                    print("Class: $class failed calling $method\n");
                    throw $e;
                }
            }
        }
    }

Gives us this failure:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)
Testing that class: Mock_MyModel_9ee820db has method: bootMyTrait because of Trait: App\MyTrait
Class: Mock_MyModel_9ee820db has method: bootMyTrait
Class: Mock_MyModel_9ee820db failed calling bootMyTrait


Time: 129 ms, Memory: 18.00Mb

There was 1 error:

1) ExampleTest::testTraitBooting
PHPUnit_Framework_MockObject_BadMethodCallException:

mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:326
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:309
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:296
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:277
mock-bootable-laravel-model-trait/tests/ExampleTest.php:16

I've also tried creating the mock a few different ways. Using DatabaseSoftDeletingTraitTest as an example:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel');
        $mock->shouldReceive('bootMyTrait')->once();
    }
}

But here, bootMyTrait is never called:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 149 ms, Memory: 19.25Mb

There was 1 error:

1) ExampleTest::testTraitBooting
Mockery\Exception\InvalidCountException: Method bootMyTrait() from Mockery_0_App_MyModel should be called
 exactly 1 times but called 0 times.

mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Expectation.php:271
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:297
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:282
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery.php:142
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:122

So, I can move the code I'm doing in the boot method to a ServiceProvider, but then I'll need to register each Model that uses the trait. This feels dirty, and using the boot method seems appropriate. So I think I've either hit a bug, or am Mocking the trait-using-model incorrectly. I've looked at getMockForTrait but I also need the mocked instance to extend Eloquent (a few of the trait's methods call eloquent methods)

If anyone sees something I missed, much appreciated

Update Apr, 22 (Friday) 2016-04-22 03:28 PM

Thanks to Marcin, we have a solution!

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel')->makePartial();
        $mock->shouldReceive('bootMyTrait')->once();
        $mock->__construct();
    }
}