Browse Source

Added the AudioFileInspector project and updated NoteEvent to cope with MIDI files with invalid Note Off velocity (apparently Cubase can export these)

pull/1/head
markheath 19 years ago
parent
commit
44bd2a2354
  1. 126
      AudioFileInspector/AudioFileInspector.csproj
  2. 203
      AudioFileInspector/AudioFileInspectorForm.Designer.cs
  3. 226
      AudioFileInspector/AudioFileInspectorForm.cs
  4. 123
      AudioFileInspector/AudioFileInspectorForm.resx
  5. 30
      AudioFileInspector/CakewalkMapInspector.cs
  6. 88
      AudioFileInspector/FindForm.Designer.cs
  7. 29
      AudioFileInspector/FindForm.cs
  8. 120
      AudioFileInspector/FindForm.resx
  9. 13
      AudioFileInspector/IAudioFileInspector.cs
  10. 154
      AudioFileInspector/InstallScript.nsi
  11. 147
      AudioFileInspector/MidiFileInspector.cs
  12. 94
      AudioFileInspector/OptionsForm.Designer.cs
  13. 87
      AudioFileInspector/OptionsForm.cs
  14. 120
      AudioFileInspector/OptionsForm.resx
  15. 62
      AudioFileInspector/Program.cs
  16. 71
      AudioFileInspector/Properties/AssemblyInfo.cs
  17. 63
      AudioFileInspector/Properties/Resources.Designer.cs
  18. 117
      AudioFileInspector/Properties/Resources.resx
  19. 26
      AudioFileInspector/Properties/Settings.Designer.cs
  20. 7
      AudioFileInspector/Properties/Settings.settings
  21. 67
      AudioFileInspector/SoundFontInspector.cs
  22. 49
      AudioFileInspector/WaveFileInspector.cs
  23. 84
      AudioFileInspector/audio_file_inspector.html
  24. 2
      MidiFileSplitter/InstallScript.nsi
  25. 1
      MidiFileSplitter/midi_file_splitter.html
  26. 6
      NAudio.sln
  27. 5
      NAudio/Changes.xml
  28. 24
      NAudio/Midi/NoteEvent.cs
  29. 4
      NAudio/Properties/AssemblyInfo.cs

126
AudioFileInspector/AudioFileInspector.csproj

@ -0,0 +1,126 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D29C1659-635C-497B-847E-FE9A5A69ED03}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AudioFileInspector</RootNamespace>
<AssemblyName>AudioFileInspector</AssemblyName>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AudioFileInspectorForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AudioFileInspectorForm.Designer.cs">
<DependentUpon>AudioFileInspectorForm.cs</DependentUpon>
</Compile>
<Compile Include="CakewalkMapInspector.cs" />
<Compile Include="FindForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FindForm.Designer.cs">
<DependentUpon>FindForm.cs</DependentUpon>
</Compile>
<Compile Include="IAudioFileInspector.cs" />
<Compile Include="MidiFileInspector.cs" />
<Compile Include="OptionsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="OptionsForm.Designer.cs">
<DependentUpon>OptionsForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="AudioFileInspectorForm.resx">
<SubType>Designer</SubType>
<DependentUpon>AudioFileInspectorForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FindForm.resx">
<SubType>Designer</SubType>
<DependentUpon>FindForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="OptionsForm.resx">
<SubType>Designer</SubType>
<DependentUpon>OptionsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="InstallScript.nsi">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Compile Include="SoundFontInspector.cs" />
<Compile Include="WaveFileInspector.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\nAudio\nAudio.csproj">
<Project>{9CABA8DA-CCF0-4808-9AA7-75F269DB2D7C}</Project>
<Name>nAudio</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="audio_file_inspector.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

203
AudioFileInspector/AudioFileInspectorForm.Designer.cs

@ -0,0 +1,203 @@
namespace AudioFileInspector
{
partial class AudioFileInspectorForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.findToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.clearLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.contentsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.textLog = new System.Windows.Forms.RichTextBox();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.editToolStripMenuItem,
this.toolsToolStripMenuItem,
this.helpToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(513, 24);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.openToolStripMenuItem,
this.exitToolStripMenuItem});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 20);
this.fileToolStripMenuItem.Text = "&File";
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.openToolStripMenuItem.Text = "&Open...";
this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.exitToolStripMenuItem.Text = "E&xit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
//
// editToolStripMenuItem
//
this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.findToolStripMenuItem});
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
this.editToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.editToolStripMenuItem.Text = "&Edit";
//
// findToolStripMenuItem
//
this.findToolStripMenuItem.Name = "findToolStripMenuItem";
this.findToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F)));
this.findToolStripMenuItem.Size = new System.Drawing.Size(155, 22);
this.findToolStripMenuItem.Text = "&Find...";
this.findToolStripMenuItem.Click += new System.EventHandler(this.findToolStripMenuItem_Click);
//
// toolsToolStripMenuItem
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.optionsToolStripMenuItem,
this.saveLogToolStripMenuItem,
this.clearLogToolStripMenuItem});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.toolsToolStripMenuItem.Text = "&Tools";
//
// optionsToolStripMenuItem
//
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
this.optionsToolStripMenuItem.Text = "&Options...";
this.optionsToolStripMenuItem.Click += new System.EventHandler(this.optionsToolStripMenuItem_Click);
//
// saveLogToolStripMenuItem
//
this.saveLogToolStripMenuItem.Name = "saveLogToolStripMenuItem";
this.saveLogToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
this.saveLogToolStripMenuItem.Text = "&Save Log...";
this.saveLogToolStripMenuItem.Click += new System.EventHandler(this.saveLogToolStripMenuItem_Click);
//
// clearLogToolStripMenuItem
//
this.clearLogToolStripMenuItem.Name = "clearLogToolStripMenuItem";
this.clearLogToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
this.clearLogToolStripMenuItem.Text = "&Clear Log";
this.clearLogToolStripMenuItem.Click += new System.EventHandler(this.clearLogToolStripMenuItem_Click);
//
// helpToolStripMenuItem
//
this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.aboutToolStripMenuItem,
this.contentsToolStripMenuItem});
this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
this.helpToolStripMenuItem.Size = new System.Drawing.Size(40, 20);
this.helpToolStripMenuItem.Text = "&Help";
//
// aboutToolStripMenuItem
//
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(129, 22);
this.aboutToolStripMenuItem.Text = "&About";
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
//
// contentsToolStripMenuItem
//
this.contentsToolStripMenuItem.Name = "contentsToolStripMenuItem";
this.contentsToolStripMenuItem.Size = new System.Drawing.Size(129, 22);
this.contentsToolStripMenuItem.Text = "&Contents";
this.contentsToolStripMenuItem.Click += new System.EventHandler(this.contentsToolStripMenuItem_Click);
//
// textLog
//
this.textLog.Dock = System.Windows.Forms.DockStyle.Fill;
this.textLog.HideSelection = false;
this.textLog.Location = new System.Drawing.Point(0, 24);
this.textLog.Name = "textLog";
this.textLog.Size = new System.Drawing.Size(513, 409);
this.textLog.TabIndex = 1;
this.textLog.Text = "";
//
// AudioFileInspectorForm
//
this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(513, 433);
this.Controls.Add(this.textLog);
this.Controls.Add(this.menuStrip1);
this.MainMenuStrip = this.menuStrip1;
this.Name = "AudioFileInspectorForm";
this.Text = "Audio File Inspector";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.AudioFileInspectorForm_FormClosed);
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AudioFileInspectorForm_DragDrop);
this.DragOver += new System.Windows.Forms.DragEventHandler(this.AudioFileInspectorForm_DragOver);
this.Load += new System.EventHandler(this.AudioFileInspectorForm_Load);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem contentsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem saveLogToolStripMenuItem;
private System.Windows.Forms.RichTextBox textLog;
private System.Windows.Forms.ToolStripMenuItem clearLogToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem findToolStripMenuItem;
}
}

226
AudioFileInspector/AudioFileInspectorForm.cs

@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace AudioFileInspector
{
partial class AudioFileInspectorForm : Form
{
List<IAudioFileInspector> inspectors;
string filterString;
int filterIndex;
string[] args;
string currentFile;
FindForm findForm;
public AudioFileInspectorForm(List<IAudioFileInspector> inspectors, string[] args)
{
InitializeComponent();
this.inspectors = inspectors;
CreateFilterString();
this.args = args;
}
private void DescribeFile(string fileName)
{
currentFile = fileName;
textLog.Text = String.Format("Opening {0}\r\n", fileName);
try
{
string extension = System.IO.Path.GetExtension(fileName).ToLower();
bool described = false;
foreach (IAudioFileInspector inspector in inspectors)
{
if (extension == inspector.FileExtension)
{
textLog.AppendText(inspector.Describe(fileName));
described = true;
break;
}
}
if (!described)
{
textLog.AppendText("Unrecognised file type");
}
}
catch (Exception ex)
{
textLog.AppendText(ex.ToString());
}
}
private void CreateFilterString()
{
StringBuilder stringBuilder = new StringBuilder();
if (inspectors.Count > 0)
{
stringBuilder.Append("All Supported Files|");
foreach (IAudioFileInspector inspector in inspectors)
{
stringBuilder.AppendFormat("*{0};", inspector.FileExtension);
}
stringBuilder.Length--;
stringBuilder.Append("|");
foreach (IAudioFileInspector inspector in inspectors)
{
stringBuilder.AppendFormat("{0}|*{1}|", inspector.FileTypeDescription, inspector.FileExtension);
}
}
stringBuilder.Append("All files (*.*)|*.*");
filterString = stringBuilder.ToString();
filterIndex = 1;
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = filterString;
ofd.FilterIndex = filterIndex;
if (ofd.ShowDialog() == DialogResult.OK)
{
filterIndex = ofd.FilterIndex;
DescribeFile(ofd.FileName);
textLog.SelectionStart = 0;
textLog.SelectionLength = 0;
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
NAudio.Utils.AboutForm aboutForm = new NAudio.Utils.AboutForm();
aboutForm.ShowDialog();
}
private void AudioFileInspectorForm_Load(object sender, EventArgs e)
{
if (args.Length > 0)
{
DescribeFile(args[0]);
}
}
private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
{
OptionsForm optionsForm = new OptionsForm(inspectors);
optionsForm.ShowDialog();
}
private void AudioFileInspectorForm_DragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}
private void AudioFileInspectorForm_DragDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
{
return;
}
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (files.Length > 0)
{
DescribeFile(files[0]);
}
}
private void saveLogToolStripMenuItem_Click(object sender, EventArgs args)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.DefaultExt = ".txt";
if (currentFile != null)
{
saveFileDialog.InitialDirectory = Path.GetDirectoryName(currentFile);
saveFileDialog.FileName = Path.GetFileNameWithoutExtension(currentFile) + ".txt";
}
saveFileDialog.Filter = "Text Files (*.txt)|*.txt";
saveFileDialog.FilterIndex = 1;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
using (StreamWriter writer = new StreamWriter(saveFileDialog.FileName))
{
string text = textLog.Text;
if (!text.Contains("\r"))
{
text = text.Replace("\n", "\r\n");
}
writer.Write(text);
}
}
catch (Exception e)
{
MessageBox.Show(
String.Format("Error saving conversion log\r\n{0}", e.Message),
Application.ProductName,
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
{
string helpFilePath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "audio_file_inspector.html");
try
{
System.Diagnostics.Process.Start(helpFilePath);
}
catch (Win32Exception)
{
MessageBox.Show("Could not display the help file", Application.ProductName);
}
}
private void clearLogToolStripMenuItem_Click(object sender, EventArgs e)
{
textLog.Clear();
}
private void findToolStripMenuItem_Click(object sender, EventArgs e)
{
if (findForm == null)
{
findForm = new FindForm(textLog);
findForm.Disposed += new EventHandler(findForm_Disposed);
}
findForm.Show(this);
}
void findForm_Disposed(object sender, EventArgs e)
{
findForm = null;
}
private void AudioFileInspectorForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (findForm != null)
{
findForm.Close();
}
}
}
}

123
AudioFileInspector/AudioFileInspectorForm.resx

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

30
AudioFileInspector/CakewalkMapInspector.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Text;
using NAudio.FileFormats.Map;
namespace AudioFileInspector
{
class CakewalkMapInspector : IAudioFileInspector
{
#region IAudioFileInspector Members
public string FileExtension
{
get { return ".map"; }
}
public string FileTypeDescription
{
get { return "Cakewalk Drum Map"; }
}
public string Describe(string fileName)
{
CakewalkMapFile mapFile = new CakewalkMapFile(fileName);
return mapFile.ToString();
}
#endregion
}
}

88
AudioFileInspector/FindForm.Designer.cs

@ -0,0 +1,88 @@
namespace AudioFileInspector
{
partial class FindForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBoxFind = new System.Windows.Forms.TextBox();
this.buttonFind = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(56, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Find what:";
//
// textBoxFind
//
this.textBoxFind.Location = new System.Drawing.Point(74, 6);
this.textBoxFind.Name = "textBoxFind";
this.textBoxFind.Size = new System.Drawing.Size(206, 20);
this.textBoxFind.TabIndex = 1;
//
// buttonFind
//
this.buttonFind.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonFind.Location = new System.Drawing.Point(205, 32);
this.buttonFind.Name = "buttonFind";
this.buttonFind.Size = new System.Drawing.Size(75, 23);
this.buttonFind.TabIndex = 2;
this.buttonFind.Text = "Find Next";
this.buttonFind.UseVisualStyleBackColor = true;
this.buttonFind.Click += new System.EventHandler(this.buttonFind_Click);
//
// FindForm
//
this.AcceptButton = this.buttonFind;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 64);
this.Controls.Add(this.buttonFind);
this.Controls.Add(this.textBoxFind);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FindForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Find";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBoxFind;
private System.Windows.Forms.Button buttonFind;
}
}

29
AudioFileInspector/FindForm.cs

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace AudioFileInspector
{
public partial class FindForm : Form
{
RichTextBox richTextBox;
public FindForm(RichTextBox richTextBox)
{
InitializeComponent();
this.richTextBox = richTextBox;
}
private void buttonFind_Click(object sender, EventArgs e)
{
richTextBox.Find(textBoxFind.Text,
richTextBox.SelectionStart +
richTextBox.SelectionLength,
RichTextBoxFinds.None);
richTextBox.ScrollToCaret();
}
}
}

120
AudioFileInspector/FindForm.resx

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

13
AudioFileInspector/IAudioFileInspector.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace AudioFileInspector
{
interface IAudioFileInspector
{
string FileExtension { get; }
string FileTypeDescription { get; }
string Describe(string fileName);
}
}

154
AudioFileInspector/InstallScript.nsi

@ -0,0 +1,154 @@
; Audio File Inspector install script
; originally based on example2 that comes with nsis
;
; This script is based on example1.nsi, but it remember the directory,
; has uninstall support and (optionally) installs start menu shortcuts.
;
; It will install example2.nsi into a directory that the user selects,
;--------------------------------
!include WordFunc.nsh
!insertmacro VersionCompare
!include LogicLib.nsh
!define VERSION "0.1"
!define FULLVERSION "0.1.1.0"
!define PRODUCT_NAME "Audio File Inspector"
!define EXECUTABLE_NAME "AudioFileInspector.exe"
; The name of the installer
Name "Audio File Inspector"
; The file to write
;OutFile "${PRODUCT_NAME} v${VERSION} Install.exe"
OutFile "audio_file_inspector_0_1_install.exe"
; The default installation directory
InstallDir "$PROGRAMFILES\Mark Heath\${PRODUCT_NAME}"
; Registry key to check for directory (so if you install again, it will
; overwrite the old one automatically)
InstallDirRegKey HKLM "Software\${PRODUCT_NAME}" "Install_Dir"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" ""
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Mark Heath"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "© 2006 Mark Heath"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${PRODUCT_NAME} Installer"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${VERSION}"
VIProductVersion "${FULLVERSION}"
;--------------------------------
; Utils
Function .onInit
Call GetDotNETVersion
Pop $0
${If} $0 == "not found"
MessageBox MB_OK|MB_ICONSTOP ".NET runtime library v2.0 or newer is required."
ExecShell "open" "http://msdn.microsoft.com/netframework/downloads/updates/default.aspx"
Abort
${EndIf}
StrCpy $0 $0 "" 1 # skip "v"
${VersionCompare} $0 "2.0" $1
${If} $1 == 2
MessageBox MB_OK|MB_ICONSTOP ".NET runtime library v2.0 or newer is required. You have $0."
ExecShell "open" "http://msdn.microsoft.com/netframework/downloads/updates/default.aspx"
Abort
${EndIf}
FunctionEnd
Function GetDotNETVersion
Push $0
Push $1
System::Call "mscoree::GetCORVersion(w .r0, i ${NSIS_MAX_STRLEN}, *i) i .r1"
StrCmp $1 "error" 0 +2
StrCpy $0 "not found"
Pop $1
Exch $0
FunctionEnd
;--------------------------------
; Pages
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
;--------------------------------
; The stuff to install
Section "Program Files (required)"
SectionIn RO
; Set output path to the installation directory.
SetOutPath $INSTDIR
; Put file there
File "${EXECUTABLE_NAME}"
; File "${EXECUTABLE_NAME}.config"
File "NAudio.dll"
File "audio_file_inspector.html"
; Write the installation path into the registry
WriteRegStr HKLM "SOFTWARE\${PRODUCT_NAME}" "Install_Dir" "$INSTDIR"
; Write the uninstall keys for Windows
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1
WriteUninstaller "uninstall.exe"
ExecWait '"$INSTDIR\${EXECUTABLE_NAME}" -install' $0
DetailPrint "Associating File Types returned $0"
SectionEnd
; Optional section (can be disabled by the user)
Section "Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${EXECUTABLE_NAME}" "" "$INSTDIR\${EXECUTABLE_NAME}" 0
SectionEnd
;--------------------------------
; Uninstaller
Section "Uninstall"
ExecWait '"$INSTDIR\${EXECUTABLE_NAME}" -uninstall' $0
DetailPrint "Removing Explorer Context Action returned $0"
; Remove registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
DeleteRegKey HKLM "SOFTWARE\${PRODUCT_NAME}"
; Remove files and uninstaller
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\${EXECUTABLE_NAME}"
Delete "$INSTDIR\${EXECUTABLE_NAME}.config"
Delete "$INSTDIR\NAudio.dll"
Delete "$INSTDIR\audio_file_inspector.html"
; Remove shortcuts, if any
Delete "$SMPROGRAMS\${PRODUCT_NAME}\*.*"
; Remove directories used
RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
RMDir "$INSTDIR"
SectionEnd

147
AudioFileInspector/MidiFileInspector.cs

@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Text;
using NAudio.Midi;
namespace AudioFileInspector
{
class MidiFileInspector : IAudioFileInspector
{
#region IAudioFileInspector Members
public string FileExtension
{
get { return ".mid"; }
}
public string FileTypeDescription
{
get { return "Standard MIDI File"; }
}
public string Describe(string fileName)
{
MidiFile mf = new MidiFile(fileName, false);
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n",
mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote);
int beatsPerMeasure = FindBeatsPerMeasure(mf.Events[0]);
for (int n = 0; n < mf.Tracks; n++)
{
foreach (MidiEvent midiEvent in mf.Events[n])
{
if(!MidiEvent.IsNoteOff(midiEvent))
{
sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, beatsPerMeasure), midiEvent);
}
}
}
return sb.ToString();
}
private string ToMBT(long absoluteTime, int ticksPerBeat, int beatsPerMeasure)
{
long measure = (absoluteTime / (ticksPerBeat * beatsPerMeasure)) + 1;
long beat = ((absoluteTime / ticksPerBeat) % beatsPerMeasure) + 1;
long tick = absoluteTime % ticksPerBeat;
return String.Format("{0}:{1}:{2}", measure, beat, tick);
}
private string ToMBT(MidiEvent midiEvent, int ticksPerBeat, List<TimeSignatureChange> timeSignatures)
{
TimeSignatureChange latestTimeSig = FindLatestTimeSig(midiEvent.AbsoluteTime,timeSignatures);
long relativeTime = midiEvent.AbsoluteTime - latestTimeSig.AbsoluteTime;
long measure = (relativeTime / (ticksPerBeat * latestTimeSig.BeatsPerMeasure)) + latestTimeSig.StartMeasureNumber;
long beat = ((relativeTime / ticksPerBeat) % latestTimeSig.BeatsPerMeasure) + 1;
long tick = relativeTime % ticksPerBeat;
return String.Format("{0}:{1}:{2}", measure, beat, tick);
}
/// <summary>
/// Find the number of beats per measure
/// (for now assume just one TimeSignature per MIDI track)
/// </summary>
private int FindBeatsPerMeasure(IEnumerable<MidiEvent> midiEvents)
{
int beatsPerMeasure = 4;
foreach (MidiEvent midiEvent in midiEvents)
{
TimeSignatureEvent tse = midiEvent as TimeSignatureEvent;
if (tse != null)
{
beatsPerMeasure = tse.Numerator;
}
}
return beatsPerMeasure;
}
private TimeSignatureChange FindLatestTimeSig(long absoluteTime, List<TimeSignatureChange> timeSignatures)
{
TimeSignatureChange latestChange = null;
foreach (TimeSignatureChange change in timeSignatures)
{
if (absoluteTime >= change.AbsoluteTime)
latestChange = change;
else
break;
}
if (latestChange != null)
{
latestChange = new TimeSignatureChange(0, 4, 1);
}
return latestChange;
}
private List<TimeSignatureChange> FindTimeSignatures(List<MidiEvent> midiEvents)
{
long currentTime = -1;
List<TimeSignatureChange> timeSignatureEvents = new List<TimeSignatureChange>();
foreach (MidiEvent midiEvent in midiEvents)
{
TimeSignatureEvent tse = midiEvent as TimeSignatureEvent;
if (tse != null)
{
if (tse.AbsoluteTime <= currentTime)
throw new ArgumentException("Unsorted Time Signatures found");
// TODO: work out how to get the start measure
int startMeasure = 1;
timeSignatureEvents.Add(new TimeSignatureChange(tse.AbsoluteTime,tse.Numerator,startMeasure));
currentTime = tse.AbsoluteTime;
}
}
return timeSignatureEvents;
}
class TimeSignatureChange
{
long absoluteTime;
int beatsPerMeasure;
int startMeasureNumber;
public long AbsoluteTime
{
get { return absoluteTime; }
}
public int BeatsPerMeasure
{
get { return beatsPerMeasure; }
}
public int StartMeasureNumber
{
get { return startMeasureNumber; }
}
public TimeSignatureChange(long absoluteTime, int beatsPerMeasure, int startMeasureNumber)
{
this.absoluteTime = absoluteTime;
this.beatsPerMeasure = beatsPerMeasure;
this.startMeasureNumber = startMeasureNumber;
}
}
#endregion
}
}

94
AudioFileInspector/OptionsForm.Designer.cs

@ -0,0 +1,94 @@
namespace AudioFileInspector
{
partial class OptionsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.buttonAssociate = new System.Windows.Forms.Button();
this.buttonDisassociate = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// buttonAssociate
//
this.buttonAssociate.Location = new System.Drawing.Point(73, 64);
this.buttonAssociate.Name = "buttonAssociate";
this.buttonAssociate.Size = new System.Drawing.Size(164, 23);
this.buttonAssociate.TabIndex = 0;
this.buttonAssociate.Text = "Recreate File Associations";
this.buttonAssociate.UseVisualStyleBackColor = true;
this.buttonAssociate.Click += new System.EventHandler(this.buttonAssociate_Click);
//
// buttonDisassociate
//
this.buttonDisassociate.Location = new System.Drawing.Point(73, 93);
this.buttonDisassociate.Name = "buttonDisassociate";
this.buttonDisassociate.Size = new System.Drawing.Size(164, 23);
this.buttonDisassociate.TabIndex = 1;
this.buttonDisassociate.Text = "Remove File Associations";
this.buttonDisassociate.UseVisualStyleBackColor = true;
this.buttonDisassociate.Click += new System.EventHandler(this.buttonDisassociate_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(290, 52);
this.label1.TabIndex = 2;
this.label1.Text = "Audio File Inspector can be set up to appear as a right-click \r\ncontext menu opti" +
"on in Windows explorer. You can recreate\r\nor remove the file associations at any" +
" time using the buttons\r\nbelow.";
//
// OptionsForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(309, 128);
this.Controls.Add(this.label1);
this.Controls.Add(this.buttonDisassociate);
this.Controls.Add(this.buttonAssociate);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "OptionsForm";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Options";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonAssociate;
private System.Windows.Forms.Button buttonDisassociate;
private System.Windows.Forms.Label label1;
}
}

87
AudioFileInspector/OptionsForm.cs

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using NAudio.Utils;
namespace AudioFileInspector
{
partial class OptionsForm : Form
{
List<IAudioFileInspector> inspectors;
public OptionsForm(List<IAudioFileInspector> inspectors)
{
InitializeComponent();
this.inspectors = inspectors;
}
private void buttonAssociate_Click(object sender, EventArgs args)
{
try
{
Associate(inspectors);
}
catch (Exception e)
{
MessageBox.Show(
String.Format("Unable to create file associations\r\n{0}", e),
Application.ProductName,
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void buttonDisassociate_Click(object sender, EventArgs args)
{
try
{
Disassociate(inspectors);
}
catch (Exception e)
{
MessageBox.Show(
String.Format("Unable to remove file associations\r\n{0}", e),
Application.ProductName,
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
public static void Disassociate(List<IAudioFileInspector> inspectors)
{
foreach (IAudioFileInspector inspector in inspectors)
{
if (!FileAssociations.IsFileTypeRegistered(inspector.FileExtension))
{
FileAssociations.RegisterFileType(inspector.FileExtension, inspector.FileTypeDescription, null);
}
string command = "\"" + Application.ExecutablePath + "\" \"%1\"";
FileAssociations.RemoveAction(
inspector.FileExtension,
"AudioFileInspector");
}
}
public static void Associate(List<IAudioFileInspector> inspectors)
{
foreach (IAudioFileInspector inspector in inspectors)
{
if (!FileAssociations.IsFileTypeRegistered(inspector.FileExtension))
{
FileAssociations.RegisterFileType(inspector.FileExtension, inspector.FileTypeDescription, null);
}
string command = "\"" + Application.ExecutablePath + "\" \"%1\"";
FileAssociations.AddAction(
inspector.FileExtension,
"AudioFileInspector",
"Describe",
command);
}
}
}
}

120
AudioFileInspector/OptionsForm.resx

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

62
AudioFileInspector/Program.cs

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace AudioFileInspector
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static int Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
List<IAudioFileInspector> inspectors = new List<IAudioFileInspector>();
inspectors.Add(new WaveFileInspector());
inspectors.Add(new MidiFileInspector());
inspectors.Add(new SoundFontInspector());
inspectors.Add(new CakewalkMapInspector());
if (args.Length > 0)
{
if (args[0] == "-install")
{
try
{
OptionsForm.Associate(inspectors);
Console.WriteLine("Created {0} file associations", inspectors.Count);
}
catch (Exception e)
{
Console.WriteLine("Unable to create file associations");
Console.WriteLine(e.ToString());
return -1;
}
return 0;
}
else if (args[0] == "-uninstall")
{
try
{
OptionsForm.Disassociate(inspectors);
Console.WriteLine("Removed {0} file associations", inspectors.Count);
}
catch (Exception e)
{
Console.WriteLine("Unable to remove file associations");
Console.WriteLine(e.ToString());
return -1;
}
return 0;
}
}
Application.Run(new AudioFileInspectorForm(inspectors,args));
return 0;
}
}
}

71
AudioFileInspector/Properties/AssemblyInfo.cs

@ -0,0 +1,71 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Audio File Inspector")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Mark Heath")]
[assembly: AssemblyProduct("Audio File Inspector")]
[assembly: AssemblyCopyright("Copyright © Mark Heath 2006")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8bb855c5-ddfc-4596-a5df-aa9059be7705")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("0.1.4.0")]
[assembly: AssemblyFileVersion("0.1.4.0")]
// build 1 - 1 Nov 2006
// initial version - moved out of WavePlayer
// extracted file describing logic into classes
// drag and drop support
// command line support
// explorer context menu support
// save analysis to text file
// installer
// command line register and unregister file associations
// build 2 - 2 Nov 2006
// fixed some installer problems
// build 3 - 10 Nov 2006
// MIDI note off events are not displayed
// Initial M:B:T support for MIDI
// build 4 - 26 Apr 2007
// Updated to work with latest code in CodePlex
// Beginnings of a find feature
// TODO list
// help file
// better error handling
// possibly: a plugin format
// options for each inspector
// describe on a separate thread
// Enhance existing:
// MIDI: riff, M:B:T
// WAV: ACID format
// Additional formats:
// WAV 64
// AIFF
// REX
// MP3
// OGG
// Project 5 pattern

63
AudioFileInspector/Properties/Resources.Designer.cs

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AudioFileInspector.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AudioFileInspector.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

117
AudioFileInspector/Properties/Resources.resx

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

26
AudioFileInspector/Properties/Settings.Designer.cs

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AudioFileInspector.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

7
AudioFileInspector/Properties/Settings.settings

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

67
AudioFileInspector/SoundFontInspector.cs

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text;
using NAudio.SoundFont;
namespace AudioFileInspector
{
class SoundFontInspector : IAudioFileInspector
{
#region IAudioFileInspector Members
public string FileExtension
{
get { return ".sf2"; }
}
public string FileTypeDescription
{
get { return "SoundFont File"; }
}
public string Describe(string fileName)
{
SoundFont sf = new SoundFont(fileName);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("{0}\r\n",sf.FileInfo);
stringBuilder.Append("Presets\r\n");
foreach(Preset p in sf.Presets)
{
stringBuilder.AppendFormat("{0}\r\n",p);
foreach(Zone z in p.Zones)
{
stringBuilder.AppendFormat(" {0}\r\n",z);
foreach(Generator g in z.Generators)
{
stringBuilder.AppendFormat(" {0}\r\n",g);
}
foreach(Modulator m in z.Modulators)
{
stringBuilder.AppendFormat(" {0}\r\n",m);
}
}
}
stringBuilder.Append("Instruments\r\n");
foreach(Instrument i in sf.Instruments)
{
stringBuilder.AppendFormat("{0}\r\n",i);
foreach(Zone z in i.Zones)
{
stringBuilder.AppendFormat(" {0}\r\n",z);
foreach(Generator g in z.Generators)
{
stringBuilder.AppendFormat(" {0}\r\n",g);
}
foreach(Modulator m in z.Modulators)
{
stringBuilder.AppendFormat(" {0}\r\n",m);
}
}
}
return stringBuilder.ToString();
}
#endregion
}
}

49
AudioFileInspector/WaveFileInspector.cs

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using NAudio.Wave;
namespace AudioFileInspector
{
class WaveFileInspector : IAudioFileInspector
{
#region IAudioFileInspector Members
public string FileExtension
{
get { return ".wav"; }
}
public string FileTypeDescription
{
get { return "Wave File"; }
}
public string Describe(string fileName)
{
StringBuilder stringBuilder = new StringBuilder();
using (WaveFileReader wf = new WaveFileReader(fileName))
{
stringBuilder.AppendFormat("{0}\r\n", wf.WaveFormat);
stringBuilder.AppendFormat("Length: {0}\r\n", wf.Length);
foreach (RiffChunk chunk in wf.ExtraChunks)
{
stringBuilder.AppendFormat("Chunk: {0}, length {1}\r\n", chunk.IdentifierAsString, chunk.Length);
byte[] data = wf.GetChunkData(chunk);
int n = 0;
foreach (byte b in data)
{
stringBuilder.AppendFormat("{0:X2} ", b);
if (++n % 8 == 0)
stringBuilder.Append("\r\n");
}
stringBuilder.Append("\r\n");
}
}
return stringBuilder.ToString();
}
#endregion
}
}

84
AudioFileInspector/audio_file_inspector.html

@ -0,0 +1,84 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Audio File Inspector</title>
</head>
<body>
<h2>
Audio File Inspector</h2>
<p>
Audio File Inspector is a simple utility that describes the contents of various
types of audio file (for example WAV files or MIDI sequences). It started out as
a developer tool to aid in writing code that reads these various formats, but has
been released because some people may find it useful for diagnosing problems playing
back various media files.</p>
<p>
Audio File Formats are notoriously vague and it is likely that you will have some
files on your computer that cause Audio File Inspector to generate an error message.
If you encounter a problem, then feel free to zip the file up and email it to me
and I will consider updating the utility to support your file.</p>
<h2>
Supported File Types</h2>
<p>
The current version of Audio File Inspector supports the following file types:</p>
<ul>
<li><b>MID</b> - This will enumerate each event in the MIDI file. At the moment it
reports the time of the event in terms of "absolute time". A future update will turn
this into measures, beats and ticks (M:B:T)</li>
<li><b>SF2</b> - This examines a SoundFont file, reporting all the instruments, zones
and audio files contained within</li>
<li><b>WAV</b> - This will report the format of the audio data, as well as providing
binary dumps of any extra chunks of information.</li>
<li><b>MAP</b> - This can extract some information from a Cakewalk drum map file.
</li>
</ul>
<h2>
Download</h2>
<p>A link to the latest version of Audio File Inspector can be found <a href="http://www.wordandspirit.co.uk/software.html#afi">
here</a>.</p>
<h2>
Installation</h2>
<p>Audio File Inspector requires the .NET framework version 2.0 to be installed.
You can download this <a href="http://msdn.microsoft.com/netframework/downloads/updates/default.aspx">
here</a>. Once you have done this you can run the installer which will add a right-click "Describe"
action to Windows Explorer for each of the supported file types.</p>
<h2>
Usage</h2>
<p>
There are a variety of ways in which you can load a file into Audio File Inspector for
analysis.</p>
<ul>
<li>Right-click a supported file in Windows explorer and click <b>"Describe"</b></li>
<li>Use the <b>File|Open</b> menu option to select a file to analyse</li>
<li>Drag a file from Windows explorer onto the title-bar of Audio File Inspector</li>
<li>You can also drag a file over the executable itself or run Audio File Inspector
from the command line with a filename as an argument.</li>
</ul>
<h2>
Tools Menu</h2>
<p>
On the tools menu you can find commands that allow you to clear the log or to save its
contents to disk (you are of course free to edit the contents in any way you like before
saving it).
There is also an options form, which in this version simply allows you to recreate or remove
the right-click "Describe" option in Windows Explorer.</p>
<h2>
Version History</h2>
<p>
The latest version of Audio File Inspector can be found at <a href="http://www.wordandspirit.co.uk/software.html#afi">
http://www.wordandspirit.co.uk/software.html</a>.
</p>
<ul>
<li>v0.1 2 Nov 2006
<ul>
<li>First public beta release</li>
<li>Support for WAV, MID, SF2 and MAP</li>
</ul>
</li>
</ul>
</body>
</html>

2
MidiFileSplitter/InstallScript.nsi

@ -14,7 +14,7 @@
RequestExecutionLevel highest
!define VERSION "0.6"
!define FULLVERSION "0.6.7.0"
!define FULLVERSION "0.6.8.0"
!define PRODUCT_NAME "MIDI File Splitter"
!define EXECUTABLE_NAME "MIDIFileSplitter.exe"

1
MidiFileSplitter/midi_file_splitter.html

@ -214,6 +214,7 @@
<ul>
<li>Fixed a sysex writing bug</li>
<li>Better preserving of event ordering</li>
<li>Can read invalid MIDI off events</li>
</ul>
</li>

6
NAudio.sln

@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAudioTests", "NAudioTests\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NAudioDemo", "NAudioDemo\NAudioDemo.csproj", "{C37A547B-F31E-45FB-870A-CFA704D06152}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioFileInspector", "AudioFileInspector\AudioFileInspector.csproj", "{D29C1659-635C-497B-847E-FE9A5A69ED03}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -43,6 +45,10 @@ Global
{C37A547B-F31E-45FB-870A-CFA704D06152}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C37A547B-F31E-45FB-870A-CFA704D06152}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C37A547B-F31E-45FB-870A-CFA704D06152}.Release|Any CPU.Build.0 = Release|Any CPU
{D29C1659-635C-497B-847E-FE9A5A69ED03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D29C1659-635C-497B-847E-FE9A5A69ED03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D29C1659-635C-497B-847E-FE9A5A69ED03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D29C1659-635C-497B-847E-FE9A5A69ED03}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

5
NAudio/Changes.xml

@ -690,4 +690,9 @@
<desc>Some improvements to MIDI out interop</desc>
<desc>Test application can now send test MIDI out messages</desc>
</change>
<change>
<version>1.0.113.0</version>
<date>26 Apr 2007</date>
<desc>Allow invalid NoteOff velocities to be read from a MIDI file</desc>
</change>
</changes>

24
NAudio/Midi/NoteEvent.cs

@ -9,8 +9,8 @@ namespace NAudio.Midi
/// </summary>
public class NoteEvent : MidiEvent
{
private byte noteNumber;
private byte velocity;
private int noteNumber;
private int velocity;
/// <summary>
/// Reads a NoteEvent from a stream of MIDI data
@ -18,8 +18,14 @@ namespace NAudio.Midi
/// <param name="br">Binary Reader for the stream</param>
public NoteEvent(BinaryReader br)
{
NoteNumber = br.ReadByte();
Velocity = br.ReadByte();
NoteNumber = br.ReadByte();
velocity = br.ReadByte();
// it seems it is possible for cubase
// to output some notes with a NoteOff velocity > 127
if (velocity > 127)
{
velocity = 127;
}
}
/// <summary>
@ -62,7 +68,7 @@ namespace NAudio.Midi
{
throw new ArgumentOutOfRangeException("Note number must be in the range 0-127");
}
noteNumber = (byte)value;
noteNumber = value;
}
}
@ -81,7 +87,7 @@ namespace NAudio.Midi
{
throw new ArgumentOutOfRangeException("Velocity must be in the range 0-127");
}
velocity = (byte)value;
velocity = value;
}
}
@ -165,7 +171,7 @@ namespace NAudio.Midi
return String.Format("{0} {1} Vel:{2}",
base.ToString(),
this.NoteName,
this.velocity);
this.Velocity);
}
/// <summary>
@ -174,8 +180,8 @@ namespace NAudio.Midi
public override void Export(ref long absoluteTime, BinaryWriter writer)
{
base.Export(ref absoluteTime, writer);
writer.Write(noteNumber);
writer.Write(velocity);
writer.Write((byte)noteNumber);
writer.Write((byte)velocity);
}
}
}

4
NAudio/Properties/AssemblyInfo.cs

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.112.0")]
[assembly: AssemblyFileVersion("1.0.112.0")]
[assembly: AssemblyVersion("1.0.113.0")]
[assembly: AssemblyFileVersion("1.0.113.0")]
Loading…
Cancel
Save