Ubuntu で C#:スタンダード MIDI ファイルを作成する
こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 環境の C# / .NET からスタンダード MIDI ファイルを作成する方法を紹介します。
実現すること
- Ubuntu 22.04 で C# / .NET プログラムからスタンダード MIDI ファイルを作成します。
C# には本来厳格なコーディング規則がありますが、この記事では可読性のために、一部規則に沿わない表記方法を使用しています。ご注意ください。
技術トピック
スタンダード MIDI ファイルとは?
こちらを展開してご覧いただけます。
スタンダード MIDI ファイル
スタンダード MIDI ファイル(Standard MIDI File)は、音楽の演奏データを保存および転送するためのファイル形式です。
キーワード | 内容 |
---|---|
プラットフォーム非依存性 | スタンダード MIDI ファイルは、異なる音楽ソフトウェアやデバイス間での互換性が高いため、さまざまなプラットフォームやデバイスで使用することができます。 |
軽量で効率的 | MIDI ファイルはテキストベースではなく、音楽データ自体をコンパクトに表現するため、ファイルサイズが小さく、データの転送や保存に効率的です。 |
多機能性 | MIDI ファイルは、音符、テンポ、音色、演奏のタイミングなど、音楽パフォーマンスに関するさまざまな情報を格納できます。これにより、演奏データの再生、編集、交換が容易になります。 |
インターネット上での共有 | MIDI ファイルはファイルサイズが小さく、再生には音源が必要ですが、音楽データを簡単に共有できるため、ウェブ上での楽曲の交換や共有が容易です。 |
作曲や編曲の効率化 | MIDI ファイルは楽曲の構成要素を表現するため、作曲家や編曲家は作業を効率化し、既存の MIDI データを編集して新しいアレンジを作成することができます。 |
教育や学習のツール | MIDI ファイルは、音楽教育や学習のツールとして広く使用されます。演奏や作曲の練習に活用したり、楽曲の分析や学習を支援したりすることができます。 |
開発環境
- Windows 11 Home 22H2 を使用しています。
WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。
WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
.NET SDK ※ こちらの関連記事からインストール方法をご確認いただけます
$ dotnet --list-sdks
7.0.202 [/usr/share/dotnet/sdk]
$ dotnet --version
7.0.202
作成する音楽の仕様
ドレミファソラシド を4回繰り返す
この記事では、MIDI や スタンダード MIDI ファイル(SMF) の仕様の詳細などは説明しておりません。ご了承ください。
MIDI ファイルを作成する手順
プロジェクトを作成
プロジェクトルートフォルダに移動します。
※ ~/tmp をプロジェクトルートフォルダとします。
$ cd ~/tmp
コンソールアプリを作成します。
※ MIDIApp がアプリ名です。
$ dotnet new console -o MIDIApp -f net7.0
一度コンソールアプリをビルド・実行します。
$ cd ~/tmp/MIDIApp
$ dotnet run
Hello, World!
ここまでの作業で、C# / .NET コンソールアプリの雛形が作成できました😋
ライブラリの追加
SMF バイナリファイルを生成できる Sanford.Multimedia.Midi パッケージを NuGet で取得します。
$ dotnet add package Sanford.Multimedia.Midi
パッケージを確認します。
$ dotnet list package
プロジェクト 'MIDIApp' に次のパッケージ参照が含まれています
[net7.0]:
最上位レベル パッケージ 要求済み 解決済み
> Sanford.Multimedia.Midi 6.6.2 6.6.2
NU1701 警告を抑制します。
Sanford.Multimedia.Midi は元々 .NET 7 用には作られていないのでビルド時などに警告が表示されます。しかし、今回の利用には支障がない為、以下の記述を追加して NU1701 警告表示を抑制します。
$ vim MIDIApp.csproj
<Project Sdk="Microsoft.NET.Sdk">
<!-- 省略 -->
<PropertyGroup>
<NoWarn>NU1701</NoWarn>
</PropertyGroup>
</Project>
ここまでの手順で、プロジェクトに Sanford.Multimedia.Midi のパッケージを組み込むことができました。
コードの追加と修正
スタンダード MIDI ファイルに対応するバイト配列に変換するクラスを作成します。
$ vim Converter.cs
using static System.Convert;
using static System.Math;
namespace MIDIApp {
// コンバータークラス
public static class Converter {
// 数値 BPM を SMF のテンポ情報に変換
public static byte[] ToByteTempo(int tempo) {
double double_value = 60 * Pow(x: 10, y: 6) / tempo;
string hex = int.Parse(s: Round(a: double_value).ToString()).ToString("X6"); // 16進数6桁の変換
char[] char_array = hex.ToCharArray();
return new byte[3]{ // 3バイトで返す
ToByte(value: char_array[0].ToString() + char_array[1].ToString(), fromBase: 16),
ToByte(value: char_array[2].ToString() + char_array[3].ToString(), fromBase: 16),
ToByte(value: char_array[4].ToString() + char_array[5].ToString(), fromBase: 16)
};
}
// 文字列をバイト配列に変換
public static byte[] ToByteArray(string target) {
return target.ToCharArray().Select(selector: x => ToByte(value: x)).ToArray();
}
}
}
Program.cs を修正します。
$ vim Program.cs
using static System.Console;
using Sanford.Multimedia.Midi;
using static Sanford.Multimedia.Midi.ChannelCommand;
using static Sanford.Multimedia.Midi.MetaType;
using static MIDIApp.Converter;
namespace MIDIApp {
class Program {
static void Main(string[] args) {
// シーケンスの作成
Sequence sequence = new();
sequence.Format = 1;
int channel = 0; // MIDI チャンネル番号
int velocity = 112; // ノートオン時のベロシティ
int bpm = 120; // テンポ
int eighth_note_length = 6000 / (bpm * 4); // 8分音符の長さ(ミリ秒)
string song_name = "New Song 001"; // 曲名
string copyright = "STUDIO Awesome"; // 著作権
// ノートの長さを 8分音符に設定
int duration = eighth_note_length;
// ドレミファソラシドの音階を設定
int[] notes = { 60, 62, 64, 65, 67, 69, 71, 72 };
notes = Enumerable.Repeat(notes, 4).SelectMany(n => n).ToArray(); // 4回繰り返す
// コンダクタートラックの設定
Track conductor_track = new();
conductor_track.Insert(position: 0, new MetaMessage(Tempo, ToByteTempo(bpm)));
conductor_track.Insert(position: 0, new MetaMessage(TrackName, ToByteArray(song_name)));
conductor_track.Insert(position: 0, new MetaMessage(Copyright, ToByteArray(copyright)));
sequence.Add(item: conductor_track);
// シーケンストラックの設定
Track sequence_track = new();
sequence_track.Insert(position: 0, new MetaMessage(TrackName, ToByteArray("Melody")));
sequence.Add(item: sequence_track);
// 音階の設定
int tick = 0; // 時間のトラッキング用変数
foreach (int note_number in notes) {
// ノートオンイベントの作成
sequence_track.Insert(position: tick, new ChannelMessage(NoteOn, channel, note_number, velocity));
// 次のノートまでの時間を加算
tick += duration;
// ノートオフイベントの作成
sequence_track.Insert(position: tick, new ChannelMessage(NoteOff, channel, note_number, 0));
}
// MIDI ファイルの保存
sequence.Save($"{song_name.Replace(" ", "_")}.mid");
WriteLine("completed.");
}
}
}
ターミナルから実行します。
$ dotnet run
completed.
プロジェクトフォルダに以下の MIDI ファイルが出力されます。
New_Song_001.mid
ここまでの手順で、Ubuntu の C# / .NET からスタンダード MIDI ファイルを作成することができました。作成した MIDI ファイルは、Windows 11 であれば標準の Windows メディアプレイヤーなどから再生することが可能です😋
まとめ
Ubuntu 22.04 で C# からスタンダード MIDI ファイルを作成して出力することができました。
どうでしたか? Window 11 の WSL Ubuntu に、C# / .NET の開発環境を手軽に構築することができます。ぜひお試しください。今後も .NET の開発環境などを紹介していきますので、ぜひお楽しみにしてください。