成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊使用Rust制作MIDI鋼琴程序,你學(xué)會(huì)了嗎?

開發(fā) 前端
讓我們定義SynthApp結(jié)構(gòu)體,它是一個(gè)egui應(yīng)用程序。它有合成器對(duì)象和方法來執(zhí)行音符的開/關(guān),在eframe::App的update方法中處理鍵盤事件。

本文讓我們使用Rust實(shí)現(xiàn)一個(gè)簡(jiǎn)單的MIDI Piano應(yīng)用程序。

首先,使用以下命令創(chuàng)建一個(gè)Rust新項(xiàng)目:

cargo new midi-rs

然后在Cargo.toml文件中加入依賴項(xiàng):

[dependencies]
eframe = "0.27.2"
itertools = "0.12.1"
phf = { version = "0.11", features = ["macros"] }
rustysynth = "1.3.1"
tinyaudio = "0.1.3"

  • eframe:EGUI框架——編寫可以編譯為web或本機(jī)的GUI應(yīng)用程序
  • itertools:擴(kuò)展的迭代器適配器、函數(shù)和宏。
  • phf:使用完美的散列函數(shù)在編譯時(shí)生成高效的查找表。
  • rustysynth:用純Rust編寫的MIDI 音色庫合成器
  • tinyaudio:是一個(gè)跨平臺(tái),易于使用,底層的音頻輸出庫。

這個(gè)應(yīng)用程序?qū)⒋蜷_一個(gè)接收鍵盤事件的egui窗口,這些事件被發(fā)送到rustysynth庫作為midi音符并通過tinyaudio庫輸出聲音。

首先,在src/main.rs文件中引入這些庫:

use eframe::egui;
use itertools::Itertools;
use phf::{phf_map, Map};
use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings};
use std::{
    fs::File,
    sync::{Arc, Mutex},
};
use tinyaudio::prelude::*;

接下來,定義靜態(tài)變量和常量:

const OUTPUT_PARAMS: OutputDeviceParameters = OutputDeviceParameters {
    channels_count: 2,
    sample_rate: 44100,
    channel_sample_count: 441, // 樣本的最大長(zhǎng)度
};

#[derive(Debug)]
pub struct MidiNote {
    pub note: i32,
    pub velocity: i32,
}

pub static NOTE_KEY_MAP: Map<&'static str, MidiNote> = phf_map! {
    "A" => MidiNote {
        note: 60,
        velocity: 100,
    },
    "S" => MidiNote {
        note: 62,
        velocity: 100,
    },
    "D" => MidiNote {
        note: 64,
        velocity: 100,
    },
    "F" => MidiNote {
        note: 65,
        velocity: 100,
    },
    "G" => MidiNote {
        note: 67,
        velocity: 100,
    },
};

OUTPUT_PARAMS是tinyaudio的參數(shù)。MidiNote持有MIDI音符的音符數(shù)和速度,用rustysynth播放它。它們被保存在一個(gè)靜態(tài)映射中,使用一個(gè)由按鍵值索引的phf_map!宏。

讓我們定義SynthApp結(jié)構(gòu)體,它是一個(gè)egui應(yīng)用程序。它有合成器對(duì)象和方法來執(zhí)行音符的開/關(guān),在eframe::App的update方法中處理鍵盤事件。

struct SynthApp {
    synthesizer: Arc<Mutex<Synthesizer>>,
    midi_channel: i32,
}

impl SynthApp {
    fn note_on(&mut self, key: &str) {
        let note = match NOTE_KEY_MAP.get(key) {
            Some(note) => note,
            None => return,
        };
        self.synthesizer
            .lock()
            .unwrap()
            .note_on(self.midi_channel, note.note, note.velocity)
    }

    fn note_off(&mut self, key: &str) {
        let note = match NOTE_KEY_MAP.get(key) {
            Some(note) => note,
            None => return,
        };
        self.synthesizer
            .lock()
            .unwrap()
            .note_off(self.midi_channel, note.note);
    }
}

impl eframe::App for SynthApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        ctx.input(|i| {
            for key_str in NOTE_KEY_MAP.keys() {
                if let Some(key) = egui::Key::from_name(key_str) {
                    if i.key_pressed(key) {
                        self.note_on(key_str);
                    } else if i.key_released(key) {
                        self.note_off(key_str);
                    }
                }
            }
        });

        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("My egui Application");
            ui.label(format!("Midi channel {}", self.midi_channel));
        });
    }
}

在互聯(lián)網(wǎng)上有很多不錯(cuò)的音色庫,我們使用TimGM6mb.sf2,

可以在以下地址下載:

https://github.com/craffel/pretty-midi/blob/main/pretty_midi/TimGM6mb.sf2

將下載好的文件放入到項(xiàng)目的根目錄下。

最后,我們編寫main函數(shù),合成器保存在Arc<Mutex<…>>中,以便run_output_device和SynthApp都可以訪問它。

fn main() -> Result<(), eframe::Error> {
    // 加載音色庫
    let mut sf2 = File::open("TimGM6mb.sf2").unwrap();
    let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap());

    // 創(chuàng)建MIDI文件序列器
    let settings = SynthesizerSettings::new(OUTPUT_PARAMS.sample_rate as i32);
    let synthesizer = Arc::new(Mutex::new(
        Synthesizer::new(&sound_font, &settings).unwrap(),
    ));

    // 運(yùn)行輸出設(shè)備
    let synth_c = synthesizer.clone();
    let mut left: Vec<f32> = vec![0_f32; OUTPUT_PARAMS.channel_sample_count];
    let mut right: Vec<f32> = vec![0_f32; OUTPUT_PARAMS.channel_sample_count];
    let _device = run_output_device(OUTPUT_PARAMS, move |data| {
        synth_c
            .lock()
            .unwrap()
            .render(&mut left[..], &mut right[..]);
        for (i, value) in left.iter().interleave(right.iter()).enumerate() {
            data[i] = *value;
        }
    })
    .unwrap();

    // eframe
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 480.0]),
        ..Default::default()
    };
    eframe::run_native(
        "My egui App",
        options,
        Box::new(|_cc| {
            Box::new(SynthApp {
                synthesizer,
                midi_channel: 0,
            })
        }),
    )
}

執(zhí)行cargo run,結(jié)果如圖:

圖片圖片

一旦出現(xiàn)窗口,按鍵盤的ASDFG鍵,就會(huì)播放音符。

為了進(jìn)一步探索,你可以通過添加一些UI和樂器來嘗試egui和rustysynth的各種功能。

責(zé)任編輯:武曉燕 來源: coding到燈火闌珊
相關(guān)推薦

2023-10-10 11:04:11

Rust難點(diǎn)內(nèi)存

2024-08-19 10:24:14

2023-10-31 14:04:17

Rust類型編譯器

2024-06-12 08:36:25

2024-03-05 10:09:16

restfulHTTPAPI

2022-12-26 07:48:04

敏捷項(xiàng)目

2022-03-05 23:29:18

LibuvwatchdogNode.js

2022-12-14 08:31:43

#error編譯命令

2023-01-29 08:08:34

并發(fā)庫conc通用庫

2023-07-10 08:36:21

工具pptword

2022-09-26 08:49:11

Java架構(gòu)CPU

2022-04-13 09:01:45

SASSCSS處理器

2022-12-08 10:49:43

2022-07-11 09:00:37

依賴配置文件Mybati

2023-03-07 07:50:15

Transactio事務(wù)代碼

2024-11-08 08:56:01

2024-03-04 07:41:18

SpringAOPOOP?

2022-12-27 08:45:00

繪制菜單符號(hào)

2022-10-11 08:48:08

HTTP狀態(tài)碼瀏覽器

2024-02-02 11:03:11

React數(shù)據(jù)Ref
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 手机在线不卡av | 国产一级久久久久 | 国产女人第一次做爰毛片 | 亚洲一区精品在线 | 中文字幕av亚洲精品一部二部 | 国产一级片免费视频 | 国产精品国产三级国产aⅴ无密码 | 亚洲成人综合网站 | 97国产精品 | 91久久精品一区 | 久久综合久色欧美综合狠狠 | 久久久久久国产精品久久 | 久久99精品久久久久子伦 | 午夜视频一区二区三区 | 国产亚洲网站 | 久久综合久久久 | 亚洲男人的天堂网站 | 婷婷激情在线 | 国产成人精品网站 | 黄色大片在线 | 日韩欧美专区 | 欧州一区二区三区 | 欧美国产大片 | 日韩在线视频一区 | 日韩精品一区二区三区在线观看 | 国产精品久久久久影院色老大 | 视频一区在线 | 欧美美女被c | 久久国产综合 | 国产a视频| 欧美精品在线免费观看 | 黄色免费网站在线看 | 国产91综合 | 九九视频在线观看视频6 | 精品中文字幕视频 | 午夜视频在线免费观看 | 亚洲网一区| 在线欧美 | 久久精品视频一区二区三区 | 国产免费一级一级 | 国产激情精品一区二区三区 |