Click here to Skip to main content
14,270,361 members

PVS.AVPlayer - MCI Sound Recorder

Rate this:
5.00 (5 votes)
Please Sign up or sign in to vote.
5.00 (5 votes)
2 Jul 2019CPOL
A brief guide for creating a sound recorder with the PVS.AVPlayer library

Version 0.92: No real update, but by using Microsoft Media Foundation in the new PVS.AVPlayer library and the changes to the main article, all code, samples and documents from the latest MCI/DirectShow version of the library can now be downloaded here. The new version of the library (without sound recorder) is available at https://www.codeproject.com/Articles/109714/PVS-AVPlayer-Audio-and-Video-Player-Library.

Library size: 176 KB
Platform: Microsoft Windows - WinForms Any CPU
Requirements: Microsoft .NET Framework 2.0 or higher
License: CPOL - Free to Use

Version 0.92, Copyright © 2018 PVS The Netherlands - Free to Use

Image 1

PVS.AVPlayer sound recorder sample application 'Big Recorder'

Introduction

PVS.AVPlayer is an MCI wrapper class library for .NET developers for easy but powerful playback of movies and music or recording sounds (with a microphone or other sound input device) in your application using Microsoft Windows built-in Media Control Interface (MCI).

The main topic of the original Code Project article about this library is the player part of the library while there's little information on the recorder. Or to be more accurate, the recorder is not even mentioned in the article. So here's finally a brief guide for creating a sound recorder using the PVS.AVPlayer library.

  • PVS.AVPlayer and the sample application are compiled for .NET Framework 3.5. Other versions of the library (with exactly the same functionality) are available for .NET Framework 2.0 to 4.7 (or higher) from the link at the top of this article.
  • PVS.AVPlayer and the sample application do not contain any viruses, spyware, advertisements or other malware, do not collect any information, change nothing permanently to your computer and do not connect to the internet.

Please note that a VB.NET version of the article can be downloaded from the link at the top of this article.

Creating a Sound Recorder with the PVS.AVPlayer Library

Contents

  1. Adding PVS.AVPlayer to Your Project
  2. Creating a Sound Recorder
  3. Sound Recorder Settings
  4. Starting a Recording
  5. Stopping and Saving a Recording
  6. Input Level and Position Information
  7. Playing a Recording

1. Adding PVS.AVPlayer to Your Project

To use the PVS.AVPlayer library in your application, you have to add a reference to it in your project. Download the library from the link at the top of this article, unpack the files and open your project (or create a new one) in Visual Studio and then choose "Add Reference..." from the Project menu and find (browse) and select "PVS.AVPlayer.dll".

In order to be able to use shorter names in the Visual Studio editor, type at the top of every file of your project that's using the library:

using PVS.AVPlayer;

2. Creating a Sound Recorder

With a PVS.AVPlayer sound recorder, you can record sounds with your application by using one of the input devices (e.g., a microphone) connected to a computer. PVS.AVPlayer allows you to select such an input device, set the sound quality of the recording and save the finished recording to disk in the Waveform Audio File Format (.wav).

Besides these basic capabilities, a PVS.AVPlayer recorder offers some convenient options, like easy monitoring of the sound input level and the duration of the recording.

All you have to do is to create a recorder and subscribe to the events in which you're interested. The next example creates a recorder with 3 event handlers for handling (e.g., display) input levels, recording positions and the notification that a recording has ended and can be saved to disk:

using PVS.AVPlayer

namespace MyProject
{
    public partial class Form1 : Form
    {
        Recorder recorder1;

        public Form1()
        {
            InitializeComponent();

            recorder1 = new Recorder();
            recorder1.InputDevice.Index = 0; // use the system's default input device

            recorder1.Events.RecorderInputLevelChanged += InputLevelChanged;
            if (recorder1.LastError) ... // if LastError is true, there's no input device

            recorder1.Events.RecorderPositionChanged += PositionChanged;
            recorder1.Events.RecorderSaveRequest += SaveRequest;
        }

        private void InputLevelChanged (object sender, InputLevelEventArgs e)
        {
             // ... the sound input (volume) level has changed
        }

        private void PositionChanged (object sender, RecorderPosEventArgs e)
        {
             // ... the recording position has changed.
        }

        private void SaveRequest (object sender, EventArgs e)
        {
            // ... a recording has ended and can be saved to a file
        }
    }
}

The recorder's LastError property holds a value indicating whether the last instruction failed. You can get a description of the error from the recorder1.LastErrorString property.

3. Sound Recorder Settings

As you usually don't know which input devices are available on a system or what their names are, you can get a list (string array) of the names of available devices with:

string[] devices = recorder1.InputDevice.GetDevices();

An input device can be selected from this list by using its name or (zero based) index in the list:

    recorder1.InputDevice.Index = 1;  // set the second device from the list as input device
    if (recorder1.LastError) ...      // if LastError is true, 
                                      // setting the input device has failed

A recorder has no default input device: you have to select an input device before you can use a recorder. Usually, you would let a user select an input device, but if you just want to use the system's default input device (as set in the system sound control panel), you can use:

recorder1.InputDevice.Index = 0;  // use the system's default input device (if any)

It is also quite possible that there are no (necessary) input devices available because none is installed or enabled. You can use the recorder's ShowAudioInputPanel method to open the system's sound control panel for the user to edit the device settings, e.g., enabling a device, but:

Channels and Quality Settings

The remaining settings can be changed by using the following recorder properties:

recorder1.Channels = Channels.Stereo;
recorder1.Bits = Bits.Bits16;
recorder1.SampleRate = SampleRate.Samples44100;

Please note that using high quality recording settings (e.g., 16 bits, 44100 Hz) may result in (very) large file sizes.

Changing the settings of the recorder during recording can yield unexpected results, especially when the input device is changed. Although a recorder allows you to do so, it's not recommended to change the recorder settings while recording.

4. Starting a Recording

Once you have created a recorder and its settings are set correctly, you can start recording with:

recorder1.Record(); // start a new recording (same as recorder1.Start();)

At any time during a recording, you can pause and resume the recording with:

recorder1.Pause();  // temporarily stop recording
recorder1.Resume(); // continue a paused recording

The pause setting is a recorder setting, not a recording setting. This means that you can pause a recorder even if it's not recording and that you can start a 'paused recording'.

5. Stopping and Saving a Recording

A recording can be stopped with:

recorder1.Stop();

If you want to save a recording to disk, the recording has to be saved (by using the recorder's Save method) before recording stops, for example:

recorder1.Pause();
if (recorder1.Length > 0) recorder1.Save(fileName); // or show SaveFileDialog
recorder1.Stop();

More convenient would be, as in the example at the top, to subscribe to the RecorderSaveRequest event. Every time you stop a recording, your eventhandler for this event will be called (if the length of the recording is greater than 0) to allow you to save the recording.

With the recorder's Remove option, you can remove parts of a recording before saving it:

recorder1.Remove(fromPosition, toPosition);

Recordings are saved in the Waveform Audio File format (WAV, .wav). Since this is an uncompressed file format, the files can quickly become quite large. There are many free and/or online programs available to convert the recordings to a more suitable size, such as the MP3 format.

6. Input Level and Position Information

A recorder can provide continuously updated information on the sound input level and/or the position (duration or length) of a recording. You can get this information by subscribing to some of the recorder's events:

Sound Input Level Information

If you subscribe to a recorder's RecorderInputLevelChanged event...

recorder1.RecorderInputLevelChanged += recorder1_RecorderInputLevelChanged;

...you get information about the sound input level (volume) of the selected input device (e.g. a microphone) in your RecorderInputLevelChanged eventhandler:

private void recorder1_RecorderInputLevelChanged (object sender, InputLevelEventArgs e)
{
     leftInputLabel.Text = e.LeftLevel.ToString(); // example: show the values in labels
     rightInputLabel.Text = e.RightLevel.ToString();
}

The level changed events are continuously raised, even if there is no active recording. The frequency by which your eventhandler is called is determined by the interval setting of the recorder's event timer: the default value is 100 milliseconds (10 times a second), but you can change the interval with the recorder1.TimerInterval property.

The values of the input levels range from 0 to 32767 (inclusive). With mono (Channels.Mono, 1 channel) recordings only the left channel (LeftLevel) is used.

Position Information

If you subscribe to a recorder's RecorderPositionChanged event...

recorder1.Events.RecorderPositionChanged += recorder1_RecorderPositionChanged;

...you get information about the recording position (duration, length) of the current recording in your RecorderPositionChanged eventhandler:

private void recorder1_RecorderPositionChanged (object sender, RecorderPositionEventArgs e)
{
     positionLabel.Text = e.Position.ToString(); // example: show the value in a label
}

The position changed events are raised only when recording. The frequency by which your eventhandler is called is determined by the interval setting of the recorder's event timer: the default value is 100 milliseconds (10 times a second), but you can change the interval with the recorder1.TimerInterval property. However, the smallest change in the position information (time resolution) is a second (milliseconds are not measured by MCI - this differs from the MCI players position information).

If you require the length of the recording in bytes (instead of time), you can use the recorder's LengthBytes property. The length in bytes is also measured only once per second.

Image 2

7. Playing a Recording

You can play your recordings with any media player you like. But, of course, the PVS.AVPlayer library also has a player section so you can easily add a player to the sample code:

using PVS.AVPlayer

namespace MyProject
{
     public partial class Form1 : Form
    {
        Recorder recorder1;
        Player player1;

        public Form1()
        {
            InitializeComponent();
            
            recorder1 = new Recorder();
            player1 = new Player();
        }
    }
}

and play your saved recordings with (for example):

player1.Play(@"C:\Recordings\myRecording.wav");

For more information on creating a PVS.AVPlayer player, please refer to the article "PVS.AVPlayer - MCI Audio and Video Library" also here on Code Project.

History

  • 2nd July, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Peter Vegter
United States United States
No Biography provided

Comments and Discussions

 
QuestionRecorder errors Pin
habere24-Nov-17 0:23
memberhabere24-Nov-17 0:23 
AnswerRe: Recorder errors Pin
Peter Vegter24-Nov-17 1:29
memberPeter Vegter24-Nov-17 1:29 
GeneralRe: Recorder errors Pin
habere24-Nov-17 6:30
memberhabere24-Nov-17 6:30 
GeneralRe: Recorder errors Pin
Peter Vegter24-Nov-17 8:01
memberPeter Vegter24-Nov-17 8:01 
AnswerRe: Recorder errors Pin
Peter Vegter24-Nov-17 5:37
memberPeter Vegter24-Nov-17 5:37 
GeneralRe: Recorder errors Pin
habere24-Nov-17 6:34
memberhabere24-Nov-17 6:34 
GeneralRe: Recorder errors Pin
Peter Vegter24-Nov-17 10:14
memberPeter Vegter24-Nov-17 10:14 
GeneralRe: Recorder errors Pin
habere27-Nov-17 3:51
memberhabere27-Nov-17 3:51 
GeneralRe: Recorder errors Pin
Peter Vegter27-Nov-17 5:23
memberPeter Vegter27-Nov-17 5:23 
GeneralRe: Recorder errors Pin
habere27-Nov-17 3:27
memberhabere27-Nov-17 3:27 
GeneralRe: Recorder errors Pin
Peter Vegter27-Nov-17 3:42
memberPeter Vegter27-Nov-17 3:42 
AnswerRe: Recorder errors Pin
Peter Vegter28-Nov-17 7:01
memberPeter Vegter28-Nov-17 7:01 
GeneralRe: Recorder errors Pin
habere29-Nov-17 9:53
memberhabere29-Nov-17 9:53 
GeneralRe: Recorder errors Pin
Peter Vegter29-Nov-17 10:25
memberPeter Vegter29-Nov-17 10:25 
GeneralRe: Recorder errors Pin
habere30-Nov-17 22:57
memberhabere30-Nov-17 22:57 
GeneralRe: Recorder errors Pin
Peter Vegter1-Dec-17 1:29
memberPeter Vegter1-Dec-17 1:29 
GeneralRe: Recorder errors Pin
habere2-Dec-17 7:03
memberhabere2-Dec-17 7:03 
Hello Peter, I have reduced my code as much as possible (see below). When I create a new recorder at each record and dispose it after pause, save and stop operations, I have no errors. This is not the case when I use the same recorder : the error is "Le périphérique spécifié n’est pas ouvert ou n’est pas reconnu par MCI."

Regards,Christian

Public Class Form1
    Dim Recorder1 As Recorder
    Dim PVS_AVPerror_0, PVS_AVPerror_1, PVS_AVPerror_2, PVS_AVPerror_3 As String
    Dim erreur As Integer
    Dim record_in_progress As Boolean
    Dim tentatives As Integer
    Dim success As Integer
    Dim input_buf As Byte() 'octets lus, fichier *.wav brut

    Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Recorder1 = New Recorder()        'create a new recorder
        Recorder1.InputDevice.Name = "IN (DUO-CAPTURE)"
        If Not Recorder1.LastError Then
            Recorder1.Channels = Channels.Stereo
            Recorder1.Bits = Bits.Bits24
            Recorder1.SampleRate = SampleRate.Samples44100
        Else
            MsgBox("Vérifier le cordon USB")
            Close()
        End If
        success = 0
        tentatives = 0
        Button1.Text = "Start Record"
        Button2.Text = "Stop and save"
        record_in_progress = False
        Recorder1.Dispose()
        My.Computer.Audio.Play("c:\logs_resistance\signal_out.wav", AudioPlayMode.BackgroundLoop)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click   'start record
        If Not record_in_progress Then
            Recorder1 = New Recorder()        'create a new recorder
            Recorder1.InputDevice.Name = "IN (DUO-CAPTURE)"
            Recorder1.Channels = Channels.Stereo
            Recorder1.Bits = Bits.Bits24
            Recorder1.SampleRate = SampleRate.Samples44100
            Button2.BackColor = Color.LightGray
            tentatives = tentatives + 1
            Recorder1.Record()
            PVS_AVPerror_0 = Recorder1.LastErrorString()
            Button1.BackColor = Color.LightGreen
            record_in_progress = True
        End If
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click   'stop and save
        If record_in_progress Then
            Recorder1.Pause()
            Recorder1.Save("c:\logs_resistance\signals_in.wav", False)
            input_buf = My.Computer.FileSystem.ReadAllBytes("c:\logs_resistance\signals_in.wav")
            Dim input_buf_samples As Integer = BitConverter.ToInt32(input_buf, 40) / 6
            If Recorder1.Length > 0 Then
                success = success + 1
                Button2.BackColor = Color.LightGreen
            Else
                Button2.BackColor = Color.LightSalmon
                erreur = erreur + 1
            End If
        End If
        Recorder1.Stop()
        Recorder1.Dispose()
        record_in_progress = False
        Button1.BackColor = Color.LightGray
        Dim test_2 As Boolean = Recorder1.Recording()
    End Sub

End Class

GeneralRe: Recorder errors Pin
Peter Vegter2-Dec-17 7:50
memberPeter Vegter2-Dec-17 7:50 
Questioninput level metering Pin
Member 1208593129-Nov-16 4:05
memberMember 1208593129-Nov-16 4:05 
AnswerRe: input level metering Pin
Peter Vegter29-Nov-16 8:02
memberPeter Vegter29-Nov-16 8:02 
GeneralRe: input level metering Pin
Member 1208593130-Nov-16 4:32
memberMember 1208593130-Nov-16 4:32 
GeneralRe: input level metering Pin
Peter Vegter30-Nov-16 4:44
memberPeter Vegter30-Nov-16 4:44 
GeneralRe: input level metering Pin
Member 1208593130-Nov-16 5:23
memberMember 1208593130-Nov-16 5:23 
GeneralRe: input level metering Pin
Peter Vegter30-Nov-16 5:37
memberPeter Vegter30-Nov-16 5:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 4 Aug 2016

Stats

27.6K views
2.2K downloads
12 bookmarked