Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracks can be mapped to multiple channels. #37

Merged
merged 1 commit into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

(Breaking Change) Track mappings now support mapping to multiple channels.

## [0.1.3] - MIDI tuning, accuracy.

MIDI playback is now more accurate and has been tuned to be more in time with audio
Expand Down
2 changes: 1 addition & 1 deletion src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub trait Device: fmt::Display + std::marker::Send + std::marker::Sync {
fn play(
&self,
song: Arc<Song>,
mappings: &HashMap<String, u16>,
mappings: &HashMap<String, Vec<u16>>,
cancel_handle: CancelHandle,
play_barrier: Arc<Barrier>,
) -> Result<(), Box<dyn Error>>;
Expand Down
23 changes: 12 additions & 11 deletions src/audio/cpal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
fn play(
&self,
song: Arc<Song>,
mappings: &HashMap<String, u16>,
mappings: &HashMap<String, Vec<u16>>,
cancel_handle: CancelHandle,
play_barrier: Arc<Barrier>,
) -> Result<(), Box<dyn Error>> {
Expand All @@ -137,7 +137,7 @@
fn play_format<S>(
&self,
song: Arc<Song>,
mappings: &HashMap<String, u16>,
mappings: &HashMap<String, Vec<u16>>,
cancel_handle: CancelHandle,
play_barrier: Arc<Barrier>,
) -> Result<(), Box<dyn Error>>
Expand Down Expand Up @@ -167,6 +167,7 @@
let num_channels = *mappings
.iter()
.map(|entry| entry.1)
.flatten()

Check warning on line 170 in src/audio/cpal.rs

View check run for this annotation

Codecov / codecov/patch

src/audio/cpal.rs#L170

Added line #L170 was not covered by tests
.max()
.ok_or("no max channel found")?;

Expand Down Expand Up @@ -282,9 +283,9 @@
let track2 = Track::new("test 2".into(), tempwav2_path, Some(1))?;

let song = Song::new("song name".into(), None, None, vec![track1, track2])?;
let mut mappings: HashMap<String, u16> = HashMap::new();
mappings.insert("test 1".into(), 1);
mappings.insert("test 2".into(), 4);
let mut mappings: HashMap<String, Vec<u16>> = HashMap::new();
mappings.insert("test 1".into(), vec![1]);
mappings.insert("test 2".into(), vec![4]);

let source = song.source::<i32>(&mappings)?;
let (tx, rx) = channel();
Expand Down Expand Up @@ -324,9 +325,9 @@
let track2 = Track::new("test 2".into(), tempwav2_path, Some(1))?;

let song = Song::new("song name".into(), None, None, vec![track1, track2])?;
let mut mappings: HashMap<String, u16> = HashMap::new();
mappings.insert("test 1".into(), 1);
mappings.insert("test 2".into(), 4);
let mut mappings: HashMap<String, Vec<u16>> = HashMap::new();
mappings.insert("test 1".into(), vec![1]);
mappings.insert("test 2".into(), vec![4]);

let source = song.source::<i32>(&mappings)?;
let (tx, rx) = channel();
Expand Down Expand Up @@ -359,9 +360,9 @@
let track2 = Track::new("test 2".into(), tempwav2_path, Some(1))?;

let song = Song::new("song name".into(), None, None, vec![track1, track2])?;
let mut mappings: HashMap<String, u16> = HashMap::new();
mappings.insert("test 1".into(), 1);
mappings.insert("test 2".into(), 4);
let mut mappings: HashMap<String, Vec<u16>> = HashMap::new();
mappings.insert("test 1".into(), vec![1]);
mappings.insert("test 2".into(), vec![4]);

let source = song.source::<i32>(&mappings)?;
let (tx, rx) = channel();
Expand Down
2 changes: 1 addition & 1 deletion src/audio/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl super::Device for Device {
fn play(
&self,
song: Arc<Song>,
_: &HashMap<String, u16>,
_: &HashMap<String, Vec<u16>>,
cancel_handle: CancelHandle,
play_barrier: Arc<Barrier>,
) -> Result<(), Box<dyn Error>> {
Expand Down
2 changes: 1 addition & 1 deletion src/config/trackmappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ use serde::Deserialize;
pub(super) struct TrackMappings {
// The individual track mappings.
#[serde(flatten)]
pub track_mappings: HashMap<String, u16>,
pub track_mappings: HashMap<String, Vec<u16>>,
}
2 changes: 1 addition & 1 deletion src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ mod test {
#[tokio::test(flavor = "multi_thread")]
async fn test_controller() -> Result<(), Box<dyn Error>> {
let driver = Arc::new(TestDriver::new(TestEvent::Unset));
let mappings: HashMap<String, u16> = HashMap::new();
let mappings: HashMap<String, Vec<u16>> = HashMap::new();
let device = Arc::new(audio::test::Device::get("mock-device"));
let songs = config::get_all_songs(&PathBuf::from("assets/songs"))?;
let playlist =
Expand Down
2 changes: 1 addition & 1 deletion src/controller/midi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ mod test {
playlist_event.write(&mut playlist_buf)?;

let device = Arc::new(audio::test::Device::get("mock-device"));
let mappings: HashMap<String, u16> = HashMap::new();
let mappings: HashMap<String, Vec<u16>> = HashMap::new();
let songs = config::get_all_songs(&PathBuf::from("assets/songs"))?;
let playlist =
config::parse_playlist(&PathBuf::from("assets/playlist.yaml"), songs.clone())?;
Expand Down
10 changes: 8 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,21 @@
repository_path,
song_name,
} => {
let mut converted_mappings: HashMap<String, u16> = HashMap::new();
let mut converted_mappings: HashMap<String, Vec<u16>> = HashMap::new();

Check warning on line 176 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L176

Added line #L176 was not covered by tests
for mapping in mappings.split(',') {
let track_and_channel: Vec<&str> = mapping.split('=').collect();
if track_and_channel.len() != 2 {
return Err("malformed track to channel mapping".into());
};
let track = track_and_channel[0];
let channel = track_and_channel[1].parse::<u16>()?;
converted_mappings.insert(track.into(), channel);
if !converted_mappings.contains_key(track.into()) {
converted_mappings.insert(track.into(), vec![]);

Check warning on line 185 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L184-L185

Added lines #L184 - L185 were not covered by tests
}
converted_mappings
.get_mut(track.into())

Check warning on line 188 in src/main.rs

View check run for this annotation

Codecov / codecov/patch

src/main.rs#L187-L188

Added lines #L187 - L188 were not covered by tests
.expect("expected mapping")
.push(channel);
}

let device = audio::get_device(&device_name)?;
Expand Down
8 changes: 4 additions & 4 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Player {
/// The device to play audio through.
device: Arc<dyn audio::Device>,
/// Mappings of tracks to output channels.
mappings: Arc<HashMap<String, u16>>,
mappings: Arc<HashMap<String, Vec<u16>>>,
/// The MIDI device to play MIDI back through.
midi_device: Option<Arc<dyn midi::Device>>,
/// The playlist to use.
Expand All @@ -61,7 +61,7 @@ impl Player {
/// Creates a new player.
pub fn new(
device: Arc<dyn audio::Device>,
mappings: HashMap<String, u16>,
mappings: HashMap<String, Vec<u16>>,
midi_device: Option<Arc<dyn midi::Device>>,
playlist: Arc<Playlist>,
all_songs_playlist: Arc<Playlist>,
Expand Down Expand Up @@ -154,7 +154,7 @@ impl Player {

fn play_files(
device: Arc<dyn audio::Device>,
mappings: Arc<HashMap<String, u16>>,
mappings: Arc<HashMap<String, Vec<u16>>>,
midi_device: Option<Arc<dyn midi::Device>>,
song: Arc<Song>,
cancel_handle: CancelHandle,
Expand Down Expand Up @@ -390,7 +390,7 @@ mod test {
#[tokio::test(flavor = "multi_thread")]
async fn test_player() -> Result<(), Box<dyn Error>> {
let device = Arc::new(audio::test::Device::get("mock-device"));
let mappings: HashMap<String, u16> = HashMap::new();
let mappings: HashMap<String, Vec<u16>> = HashMap::new();
let midi_device = Arc::new(midi::test::Device::get("mock-midi-device"));
let songs = config::get_all_songs(&PathBuf::from("assets/songs"))?;
let playlist =
Expand Down
27 changes: 15 additions & 12 deletions src/songs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
/// Returns a rodio source for the song.
pub fn source<S>(
&self,
track_mappings: &HashMap<String, u16>,
track_mappings: &HashMap<String, Vec<u16>>,
) -> Result<SongSource<S>, Box<dyn Error>>
where
S: Sample,
Expand Down Expand Up @@ -298,7 +298,7 @@
{
fn new(
song: &Song,
track_mapping: &HashMap<String, u16>,
track_mapping: &HashMap<String, Vec<u16>>,
) -> Result<SongSource<S>, Box<dyn Error>> {
let mut files_to_tracks = HashMap::<PathBuf, Vec<&Track>>::new();

Expand All @@ -317,6 +317,7 @@
let num_channels = *track_mapping
.iter()
.map(|entry| entry.1)
.flatten()

Check warning on line 320 in src/songs.rs

View check run for this annotation

Codecov / codecov/patch

src/songs.rs#L320

Added line #L320 was not covered by tests
.max()
.ok_or("no max channel found")?;

Expand All @@ -334,12 +335,14 @@
let mut file_channel_to_output_channels: HashMap<u16, Vec<usize>> = HashMap::new();
tracks.into_iter().for_each(|track| {
let file_channel = track.file_channel - 1;
if let Some(channel_mapping) = track_mapping.get(&track.name.to_string()) {
let output_channel = channel_mapping - 1;
file_channel_to_output_channels
.entry(file_channel)
.or_default()
.push(output_channel.into());
if let Some(channel_mappings) = track_mapping.get(&track.name.to_string()) {
channel_mappings.into_iter().for_each(|channel_mapping| {
let output_channel = channel_mapping - 1;
file_channel_to_output_channels
.entry(file_channel)
.or_default()

Check warning on line 343 in src/songs.rs

View check run for this annotation

Codecov / codecov/patch

src/songs.rs#L343

Added line #L343 was not covered by tests
.push(output_channel.into());
})
}
});

Expand Down Expand Up @@ -676,10 +679,10 @@
let track3 = super::Track::new("test 3".into(), tempwav3_path, Some(1))?;

let song = super::Song::new("song name".into(), None, None, vec![track1, track2, track3])?;
let mut mapping: HashMap<String, u16> = HashMap::new();
mapping.insert("test 1".into(), 1);
mapping.insert("test 2".into(), 4);
mapping.insert("test 3".into(), 4);
let mut mapping: HashMap<String, Vec<u16>> = HashMap::new();
mapping.insert("test 1".into(), vec![1]);
mapping.insert("test 2".into(), vec![4]);
mapping.insert("test 3".into(), vec![4]);

song.source(&mapping)
}
Expand Down