4 个版本
0.1.3 | 2024年5月27日 |
---|---|
0.1.2 | 2024年4月16日 |
0.1.1 | 2024年3月26日 |
0.1.0 | 2024年3月26日 |
#118 in 音频
160KB
3K SLoC
mtrack
mtrack
是一个多轨播放器,旨在在小型设备(如Raspberry Pi)上运行。它可以通过类兼容接口输出多个音频轨以及MIDI输出。这里的一般意图是允许通过脚本来远程控制 mtrack
,而不是需要舞台上的电脑或平板电脑。
免提多轨播放
mtrack
的理念是提供一种在直播情况下播放多轨的方法,而不需要使用你的手。在直播情况下,我经常发现自己需要在表演时照看DAW。 mtrack
的目的就是通过提供一种非常简单的播放歌曲的机制来避免这种情况。
mtrack
可以从多个音频文件中读取,并将这些文件中存在的声道重新排列和组合成一个单一的音频流,该流路由到类兼容音频接口。此外, mtrack
可以同时播放MIDI文件和音频,从而允许舞台设备的自动化。 mtrack
还可以在歌曲选择时发出MIDI事件,并监听MIDI事件以控制 mtrack
播放器。
mtrack 的一般行为
mtrack
希望有以下行为循环
mtrack
从用户定义的播放列表中的第一个项目开始。项目被选中,但尚未播放。- 在没有歌曲播放时,用户可以通过使用
next
和previous
事件来选择播放列表中的歌曲。当歌曲正在播放时,next
和previous
是不活跃的。 - 用户可以使用
play
事件开始播放歌曲,并使用stop
事件停止正在播放的歌曲。当歌曲正在播放时,play
将不执行任何操作,而当歌曲没有播放时,stop
也将不执行任何操作。 - 如果用户需要播放其播放列表中没有的歌曲,用户可以使用
all_songs
事件来切换到一个包含用户歌曲仓库中所有歌曲排序列表的播放列表。如果用户希望使用原始播放列表,则可以使用playlist
事件。
上述事件可以通过 MIDI 消息触发。
安装
mtrack
可以通过 cargo 安装。
$ cargo install mtrack
如果您想在启动时使用 mtrack
,建议将其复制到 /usr/local/bin
。
$ sudo cp ~/.cargo/bin/mtrack /usr/local/bin/mtrack
确定支持的设备
您可以通过运行 mtrack devices
来确定 mtrack
识别的音频设备。
$ mtrack devices
Devices:
- UltraLite-mk5 (Channels=22) (Alsa)
- bcm2835 Headphones (Channels=8) (Alsa)
括号前的名称是 mtrack
使用的标识符。因此,在引用第一个音频设备时,您将使用字符串 UltraLite-mk5
。
您还可以通过运行 mtrack midi-devices
来确定支持的 MIDI 设备。
$ mtrack midi-devices
Devices:
- Midi Through:Midi Through Port-0 14:0 (Input/Output)
- UltraLite-mk5:UltraLite-mk5 MIDI 1 28:0 (Input/Output)
第一个冒号前的名称是 mtrack
使用的标识符。在引用第二个 MIDI 设备时,您将使用字符串 UltraLite-mk5
。
mtrack 仓库和辅助文件的结构
歌曲仓库
歌曲仓库是磁盘上的一个位置,存放着您的伴奏音乐、MIDI 文件和歌曲定义。歌曲仓库不需要任何特定的布局,因为 mtrack
会尝试解析它找到的任何/所有 yaml
文件以查找歌曲定义。
歌曲
一首歌由以下部分组成
- 一个或多个音频文件。
- 可选的 MIDI 文件。
- 歌曲定义。
音频文件必须具有相同的比特率。它们的长度不必相同。mtrack 播放器将播放,直到最后一个音频(或 MIDI)文件播放完毕。
歌曲在 yaml
文件中定义
# The name of the song. This name is primarily used when constructing
# playlists for mtrack.
name: The Song Name
# An optional MIDI event to emit when the song is selected on the
# playlist. This will occur even if the song is not playing. This is
# useful to trigger events on a remote device, such as a MIDI controller.
midi_event:
type: program_change
channel: 16
program: 3
# An optional MIDI file to play along with the audio.
midi_file: Song Automation.mid
# The tracks associated with this song.
tracks:
# The click track only has one channel, so we can just indicate which output channel
# we want directly.
- name: click
file: click.wav # File paths are relative to the song.yaml file.
# Similarly, our cue only has one channel.
- name: cue
file: /mnt/song-storage/cue.wav # Or file paths can be absolute.
# Our backing track file has two channels, so we have to specify `file_channel` to let
# mtrack know which channel from the file to use.
- name: backing-track-l
file: Backing Tracks.wav
file_channel: 1
# We can re-use our backing track file and specify the other channel if we'd like to do
# stereo.
- name: backing-track-r
file: Backing Tracks.wav
file_channel: 2
# Our keys file has two channels, but we're only interested in one.
- name: keys
file: Keys.wav
file_channel: 1
---
# We can define multiple songs in one file.
name: The Song Name (alternate version)
...
我们可以使用 mtrack songs
命令测试我们的歌曲仓库
$ mtrack songs /mnt/song-storage
Songs (count: 23):
- Name: The first really cool song
Duration: 5:10
Channels: 11
Sample Rate: 44100
Midi Message: Some(Midi { channel: u4(15), message: ProgramChange { program: u7(0) } })
Midi File:None
Tracks: click, cue, backing-track-l, backing-track-r, keys
- Name: The next really cool song
...
您可以使用 mtrack play
播放单个歌曲
$ mtrack play -m my-midi-device my-audio-device click=1,cue=2 /mnt/song-storage "My cool song"
2024-03-22T21:24:25.588828Z INFO emit (midir): mtrack::midi::midir: Emitting event. device="my-midi-device:my-midi-device MIDI 1 28:0" event="Midi { channel: u4(15), message: ProgramChange { program: u7(3) } }"
2024-03-22T21:24:25.589420Z INFO player: mtrack::player: Waiting for song to finish. song="My cool song"
2024-03-22T21:24:25.589992Z INFO play song (rodio): mtrack::audio::rodio: Playing song. device="my-audio-device" song="My cool song" duration="4:14"
2024-03-22T21:24:25.676452Z INFO play song (midir): mtrack::midi::midir: Playing song MIDI. device="my-midi-device:my-midi-device MIDI 1 28:0" song="My cool song" duration="4:14"
播放列表
播放列表定义是一个简单的 yaml
文件
# This is a simple file that contains, in order, the names of all songs
# that mtrack should play. The names of the songs are defined in the
# song repository, which can be found in mtrack.yaml.
songs:
- Sound check
- A really cool song
- Another cool song
- The slow one
- A really fast one
- Outro tape
这将按照给定顺序播放指定的歌曲,等待您触发歌曲。
mtrack 进程定义
要将 mtrack 作为可由 MIDI 控制的独立播放器启动,您需要创建一个播放器配置文件
# This audio device will be matched as best as possible against the devices on your system.
# Run `mtrack devices` to see a list of the devices that mtrack recognizes.
audio_device: UltraLite-mk5
# This MIDI device will be matched as best as possible against the devices on your system.
# Run `mtrack midi-devices` to see a list of the devices that mtrack recognizes.
midi_device: UltraLite-mk5
# The directory where all of your songs are located, frequently referred to as the song repository.
# If the path is not absolute, it will be relative to the location of this file.
songs: /mnt/song-storage
# The controller definition. As of now, the valid kinds of controllers are:
# - keyboard
# - midi
# Keyboard is largely for testing and MIDI is intended for actual live usage.
controller:
kind: midi
# When mtrack recognizes this MIDI event, it will play the current song if no other song is
# currently playing.
play:
type: control_change
channel: 16
controller: 100
value: 0
# When mtrack recognizes this MIDI event, it will navigate to the previous song in the playlist
# if no other song is currently playing.
prev:
type: control_change
channel: 16
controller: 100
value: 1
# When mtrack recognizes this MIDI event, it will navigate to the next song in the playlist
# if no other song is currently playing.
next:
type: control_change
channel: 16
controller: 100
value: 2
# When mtrack recognizes this MIDI event, it will stop the currently playing song.
stop:
type: control_change
channel: 16
controller: 100
value: 3
# When mtrack recognizes this MIDI event, it will switch to the playlist of all known songs in
# your song repository.
all_songs:
type: control_change
channel: 16
controller: 100
value: 4
# When mtrack recognizes this MIDI event, it will switch to the defined playlist.
playlist:
type: control_change
channel: 16
controller: 100
value: 5
# Mappings of track names to output channels.
track_mappings:
click: 1
cue: 2
backing-track-l: 3
backing-track-r: 4
keys: 5
您可以使用 mtrack start /path/to/player.yaml /path/to/playlist.yaml
启动 mtrack
作为进程。
mtrack 在启动时
要使 mtrack
在系统启动时启动,您可以运行
$ sudo mtrack systemd > /etc/systemd/system/mtrack.service
请注意,该服务期望 mtrack
在 /usr/local/bin/mtrack
位置可用。它还期望您在 /etc/default/mtrack
中定义您的播放器配置和播放列表。该文件应包含两个变量:MTRACK_CONFIG
和 PLAYLIST
# The configuration for the mtrack player.
MTRACK_CONFIG=/mnt/storage/mtrack.yaml
# The playlist to use.
PLAYLIST=/mnt/storage/playlist.yaml
定义完成后,您可以使用以下命令启动它
$ systemctl start mtrack
现在它将启动,并且当您重启计算机时将重新启动。您可以通过运行以下命令查看 mtrack
的日志
$ journalctl -u mtrack
支持的 MIDI 事件
截至目前,以下MIDI事件可以定义为控制器和歌曲发射功能的一部分
# The note_off MIDI event acts as if a note was released.
midi_event:
type: note_off
channel: 5 # Channels are expected to be from 1-16.
note: 5
velocity: 127
---
# The note_on MIDI event acts as if a note was pressed.
midi_event:
type: note_on
channel: 5
note: 5
velocity: 127
---
# The aftertouch MIDI event acts as if an aftertouch MIDI event was sent.
midi_event:
type: aftertouch
channel: 5
note: 5
velocity: 127
---
# The control_change MIDI event can controller values.
midi_event:
type: control_change
channel: 5
controller: 12
value: 27
---
# The program_change MIDI event can change banks and instruments on various devices.
midi_event:
type: program_change
channel: 5
program: 20
---
# The aftertouch MIDI event acts as if a channel aftertouch MIDI event was sent.
midi_event:
type: channel_aftertouch
channel: 5
velocity: 127
---
# The pitch bend MIDI event acts as if a pitch bend MIDI event was sent.
midi_event:
type: pitch_bend
bend: 1234
还有更多可以实施,但这些只是我目前想到的。如果您想添加特定的任何事件,请提交一个问题。否则,我会根据需要添加它们。
已知限制
我只测试了它与MOTU UltraLite-mk5。
MIDI输出未经过充分测试,因此我不知道它与音频播放是否匹配良好。
这是我第一个Rust项目,所以这很可能是令人尴尬的、糟糕的非Rust风格。请随时提交PR以使其更好。
依赖关系
~9–44MB
~639K SLoC