Recording Audio in Windows Phone 8.1

First Words

This article points to a simple, fast way to record audio in Windows Phone 8.1. As the old Microphone class is no longer available, Windows Phone 8.1 came with new MediaCapture class to consolidate the media recording part for audio and video together. So, why waiting, let’s see how to do it!

Let’s get busy

I jotted a very simple GUI for this that has three simple buttons named “Capture Audio”, “Stop Capture” and “Play Capture”.  And it looks as follows:

CaptureAudio1

If you guys want to have a closer look at the XAML behind, peek a look:

<Page
    x:Class="CaptureSoundTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CaptureSoundTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <MediaElement x:Name="playbackElement1" ></MediaElement>
        <Button x:Name="CaptureButton" Content="Capture Audio" HorizontalAlignment="Center" Margin="0,184,0,0" VerticalAlignment="Top" Click="CaptureButton_Click" Width="145"/>
        <Button x:Name="StopCaptureButton" Content="Stop Capture" HorizontalAlignment="Center" Margin="0,284,0,0" VerticalAlignment="Top" Click="StopCaptureButton_Click" Width="145"/>
        <Button x:Name="PlayRecordButton" Content="Play Capture" HorizontalAlignment="Center" Margin="0,380,0,0" VerticalAlignment="Top" Click="PlayRecordButton_Click" Width="145"/>

    </Grid>
</Page>

It’s pretty basic, I didn’t do much here without keeping the buttons in place. There’s a MediaElement named playbackElement1 to play back the recorded video.

Now, it’s time to populate the button events here named CaptureButton_Click, StopCaptureButton_Click and PlayRecordButton_Click

Initializing and Capturing audio

To capture audio, first we need to initialize the recording. Before digging into that, let’s just initialize some variables that we might need on the journey.

private MediaCapture _mediaCaptureManager;
private StorageFile _recordStorageFile;
private bool _recording;
private bool _userRequestedRaw;
private bool _rawAudioSupported;

The MediaCapture class here is the one responsible here to capture audio and video both here. And StorageFile instance will help us store, locate and play the recorded media on our device.

So, let’s have a look how our recording initialization method looks like:

private async void InitializeAudioRecording()
{

   _mediaCaptureManager = new MediaCapture();
   var settings = new MediaCaptureInitializationSettings();
   settings.StreamingCaptureMode = StreamingCaptureMode.Audio;
   settings.MediaCategory = MediaCategory.Other;
   settings.AudioProcessing = (_rawAudioSupported &amp;&amp; _userRequestedRaw) ? AudioProcessing.Raw : AudioProcessing.Default;

   await _mediaCaptureManager.InitializeAsync(settings);

   Debug.WriteLine("Device initialised successfully");

   _mediaCaptureManager.RecordLimitationExceeded += new RecordLimitationExceededEventHandler(RecordLimitationExceeded);
    _mediaCaptureManager.Failed += new MediaCaptureFailedEventHandler(Failed);
}

So, the very first thing done here is the initialization of the MediaCapture class. Every media capture is associated with a MediaCaptureInitializationSettings instance. We’ve set the StreamingCaptureMode to Audio to make sure this is only audio recording rather than video. There were two bool variables declared before named _rawAudioSupported and _userRequestedRaw. Although I didn’t hook them up from GUI, you guys can defintiely try hooking them up from GUI and thus you can give the app a choice to record raw or pointing it to default audio processing.

The next thing to do is initializing the _mediaCaptureManager with the settings provided. I have included two event handlers for RecordingLimitExceeded and Failed. You guys can write your own handlers of course in these cases.

Now, usually you can put the InitializeAudioRecording method where your app initializes. I put it here on MainPage constructor.

Now, let’s capture audio, MediaCapture class made it really easy indeed.

private async void CaptureAudio()
{
   try
   {
     Debug.WriteLine("Starting record");
     String fileName = "record.m4a";

     _recordStorageFile = await KnownFolders.VideosLibrary.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);

     Debug.WriteLine("Create record file successfully");

     MediaEncodingProfile recordProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.Auto);
     await _mediaCaptureManager.StartRecordToStorageFileAsync(recordProfile, this._recordStorageFile);

     Debug.WriteLine("Start Record successful");

     _recording = true;
    }
    catch (Exception e)
    {
      Debug.WriteLine("Failed to capture audio");
    }
}

If you have a good look on the code you will see we declared a filename first. And then we created a file in our VideosLibrary using KnownFolders.VideosLibrary.CreateFileAsync that actually points to the media and video library of windows phone 8.1 with a given filename and we also gave a CreationCollisionOption.GenerateUniqueName that says it will create a unique name in case of collision. The next thing to do is creating a recording profile using MediaEncodingProfile class and you can get all possible recording profiles for videos and audios from here. I created a M4a audio profile using MediaEncodingProfile.CreateM4a(recordProfile, this._recordStorageFile) method.

All we have left to do is now start the recording, so  let’s go ahead and start the recording. And it’s easy as pie with _mediaCaptureManager.StartRecordToStorageFileAsync(recordProfile, this._recordStorageFile)

Stopping Recording

Stopping the recording is quiet easy too. All you have to do is call _mediaCaptureManager.StopRecordAsync()

private async void StopCapture()
{

     if (_recording)
     {
          Debug.WriteLine("Stopping recording");
          await _mediaCaptureManager.StopRecordAsync();
          Debug.WriteLine("Stop recording successful");
          _recording = false;
     }

}

Playing Recording

Playing a recording kind of consists of two tasks. First we have to open the recorded file and then play it. If you guys remember we used StorageFile _recordStorageFile to define our file that will hold the recording.

private async void PlayRecordedCapture()
{
     if (!_recording)
     {
         var stream = await _recordStorageFile.OpenAsync(FileAccessMode.Read);
         Debug.WriteLine(&quot;Recording file opened&quot;);
         playbackElement1.AutoPlay = true;
         playbackElement1.SetSource(stream, _recordStorageFile.FileType);
         playbackElement1.Play();
     }
}

So, let’s open up the file and assign the resultant stream to a source of a MediaElement on XAML. In this case that one is playBackElement1

 

Voila! You’re done, now you can play your recording. All you have to do now is assign these three methods to proper button events. For the full source please download the demo project above.

Advertisements

Using SQLite as local database with Universal Apps

The First Words

Usually when we are moving our existing Windows Phone 8 / Windows Phone Silverlight projects to Universal Apps, in most of the cases the common question that rises up is what should we use as a local database on it. And SQLite does a perfect job serving the universal apps a perfect local database. So, please keep your eyes posted here if you want to use the same database for both your projects in your universal app. So, why not get started?

Universal Apps

Univeresal Apps are the newest App Models designed for Windows Store to serve Apps in Windows Store and Windows Phone Store from a same project with shared codes as per your liking. To the ones who doesn’t know what an Uinversal App is, kindly visit this link so you can get a full idea how it works. To the ones who already know this, please continue.

SQLite With Universal App

To get SQLite going with your universal app, the first thing we should do is get SQLite for both Windows Phone 8.1 and Windows Runtime 8.1as Universal App points to both of the apps.

To install SQLite for Windows Store please visit:

http://visualstudiogallery.msdn.microsoft.com/1d04f82f-2fe9-4727-a2f9-a2db127ddc9a/view/

And you will stumble upon a screen like the following:
1

So, definitely the next thing to do is download this one, as soon as the VSIX installer is downloaded, install it. As, now we have SQLite for Windows Store here, let’s move so we can have SQLite for Windows Phone.

To install SQLite for Windows Phone 8.1 please visit:

http://visualstudiogallery.msdn.microsoft.com/5d97faf6-39e3-4048-a0bc-adde2af75d1b

This will lead to a similiar page, download the VSIX installer and install it too. The next thing we should check for whether we have installed what we need in our Visual Studio. I’m using a Visual Studio 2013 Ultimate version here and let’s go over Tools -> Extensions and Updates and go to the “SDK” section after under “Installed”. You will stumble upon SQLite for Windows Runtime and SQLite for Windows Phone 8.1 is listed as installed in your pc.

2

As now we are pretty sure that we have SQLite for Windows Phone 8.1 and Windows Store Apps, let’s create a new Universal App Project in Visual Studio.

SQLite With Universal App

Creating Univresal Apps are pretty same like other projects in Visual Studio. Just go over File->New Project and under Store Apps, let’s create a blank Universal App named UniversalSQLite.

3

In the Solution Explorer, you will see your projects divided into Windows Store, Windows Phone and Shared. Our job now is to reference SQLite into both Windows Store and Windows Phone projects so both of the projects has access to SQLite. In Windows 8.1 Solution, go over your references and add reference to the newly added SQLite libraries under extensions.

4

And do the same with Windows Phone 8.1 solution too. Go over references and add reference to the newly installed SQLite for Windows Phone 8.1 Libraries.

5
You will see some yellow excalamtion signs over the newly referenced libraries and the best thing to do right now is to build this. The first problem you are bound to see when you build is this:

6

Actually the problem says the solution itself. As these native libraries are extremely machine dependent the best thing to do here would be just go over configuration manager and set x86 as Platform for both projects.

7 8

Trying out x64 ended up XAML designer not rendering UI. So x86 is the safe choice. Don’t worry,  this will not prevent you to create the different platform version to be deployed on the store.

When you are ready just use the “Create App Packages” command. The best way to get that would be right clicking on the solution name and move over to store menu. But that’s later.

9

Get sqlite-net from Nuget

Well, if you put a build now, you will see everything has smoothed out. Now, what’d left is using SQLite. The first thing we need is a nuget package to cover all the internal intricacies we have on SQLite, thus comes in help sqlite-net  . This little nuget package is extremely handy and all you need to do to use this is to go over references and manage nuget packages. Search for sqlite-net and add it when the search results pop up.

10

This has to be done for both the Windows 8.1 and Windows Phone 8.1 projects of course as we intend to use this for both of them. You will see two classes named SQLite.cs and SQLiteAsync.cs is created into both of the projects. Just to remove duplicacies we can move them to shared project under a folder if you like.

11

Let’s get our hands dirty

So, lets get busy with some code, shall we?

Creating/Opening A Database:

To create/open a database all you have to do is someting like the following. This will actually create a database if it’s non existing or open connection to one if it’s existing.

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);

So, before doing that you might want to check whether the database exists or not.

public async Task&amp;lt;bool&amp;gt; DoesDbExist(string DatabaseName)
{
      bool dbexist = true;
      try
      {
         StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(DatabaseName);

      }
      catch
      {
         dbexist = false;
      }

      return dbexist;
}

The reason we are looking at ApplicationData.Current.LocalFolder is sqlite-net creates database by default in that place.

Creating/Opening A Database:

Before creating a table you need to have a model to define a row on that specific table. The model might look like the following:

using SQLite;


namespace UniversalSqlLite.Model
{
    [Table(&quot;Students&quot;)]
    public class Student
    {
        [PrimaryKey, AutoIncrement]
        public int id { get; set; }

        public string Name { get; set; }

        public string EnrolledCourse { get; set; }

    }
}

Now you can just go ahead an create a Table as per your wish.

public async void CreateDatabase()
{
   SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
   await connection.CreateTableAsync&amp;lt;Student&amp;gt;();
}

CreateTableAsync will create the table if it’s not there. And it will update the table description if the Model is changed in any way than the previous one. As far now, it only supports column addition. It will not destroy any existing SQLite Table. So, you don’t have to worry about redoing this with an existing table.

If you look closely, you can see that you can adore the classes and the properties in the model with attributes defined in sqllite-net library. It’s almost the same you might see in Entitiy Framework.

The full list is to be found here:

Class attribute:

  • [Table(Name)]

Property attributes:

  • [AutoIncrement]
  • [PrimaryKey]
  • [Column(Name)]
  • [Indexed] | [Indexed(string name, int order)]
  • [Unique]
  • [Ignore]
  • [MaxLength(int length)]
  • [Collation(string name)]
  • [NotNull]

Dropping a Table:

Dropping table is a piece of cake too:

public async void DropDatabase()
{
    SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
    await connection.DropTableAsync&amp;lt;Student&amp;gt;();
}

Adding Records in the Table:

Inserting into SQLite is easy as the following:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=new Student()
{
   Name=&quot;Swagata Prateek&quot;,
   EnrolledCourse=&quot;CSE 4203&quot;
};
await connection.InsertAsync(Student);

And if you feel like inserting a lot of stuff at a time why not using a list?

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);

var StudentList = new List&amp;lt;Student&amp;gt;()
{
    new Student()
    {
        Name=&quot;Swagata Prateek&quot;,
        EnrolledCourse=&quot;CSE 4203&quot;
        },
        new Student()
        {
            Name=&quot;Abidur Rahman&quot;,
            EnrolledCourse=&quot;CSE 4203&quot;
        },
        new Student()
        {
            Name=&quot;Ashiqur Rahman&quot;,
            EnrolledCourse=&quot;CSE 4203&quot;
        }
    };
            
await connection.InsertAllAsync(StudentList);

Pursue a Query

You can go for a Query in SQLite in quiet a number of ways. Let’s check out if we want to do it using LINQ, how would it be:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var queryVar=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;));

var queryResult = await queryVar.ToListAsync();
foreach (var item in queryResult)
{
    //Do your stuff
}

You can even do a manual SQL query if you feel like that:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var result = await connection.QueryAsync&amp;lt;Student&amp;gt;(&quot;Select Name FROM Students WHERE EnrolledCourse = ?&quot;, new object[] { &quot;CSE 4203&quot;});
foreach (var item in result)
{
    //Do your stuff
}

Update and Delete a Record

Any record can be updated as soon as it’s retrieved and updated back into the table.

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;)).FirstOrDefaultAsync();

if(Student != null)
{
    Student.EnrolledCourse = &quot;CSE 4503&quot;;
    await connection.UpdateAsync(Student);
}

If you want to delete the same record all you have to do is:

SQLiteAsyncConnection connection = new SQLiteAsyncConnection(&quot;Student.db&quot;);
var Student=await connection.Table&amp;lt;Student&amp;gt;().Where(x=&amp;gt;x.Name.StartsWith(&quot;Swagata&quot;)).FirstOrDefaultAsync();

if(Student != null)
{
    await connection.DeleteAsync(Student);
}

Summing up

We are going to take a little deep dive on the queries and make a sample app out of it in the next post. Meanwhile you can even go through Nicolò Carandini’s blog on SQLite with Universal app on the following links.

  1. Universal App With Sqlite Part -1
  2. Universal App With Sqlite Part -2

Hope you guys had fun!