有没有什么手机上能用的工具可以翻转播放midi音乐

提问于
最后更新于
浏览 773次
登录并提问
0

如题

具体一点来说,一个midi音乐里面是一堆音符,那么我想让这个midi音乐倒过来播放,但不是把波形倒放,而仅仅只是把所有的音符倒过来依次播放

假设现在有一个midi音乐,它里面只有一个音符,那么倒放前和倒放后是一样的

如果有一个低音区音符,一个高音区音符(顺序同我描述),则倒放后应该是高音区音符在前,低音区音符在后,但是每个音符自身的音色不变

因为我没有电脑,所以我需要这款软件能够独立的在手机上运行(而不是像网页开发者工具一样,要么得用电脑;要么就得在手机上连接电脑,然后在电脑上搞,像这样子一搞,说白了就是不要搞的除了用电脑就还得用电脑)

农药君
XP 120
农药君
提问于 2024/9/22 下午2:29:33
1

手机上能实现的办法是你找到某些DAW(基本都要付费),软件提供直接的“反转”功能。你选择所有音符,导航到“编辑”菜单,选择“反转活动 MIDI 事件”。我不知道移动端有没有这种功能(大概率没有)。

或者你自己在手机山搞个编译器部署环境,然后写个类似下面这种的脚本(需要调用mido库)

import mido

# 加载 MIDI 文件

mid = mido.MidiFile('input.mid')

# 计算总长度

total_length = sum(msg.time for msg in mid)

# 创建新的 MIDI 文件

out_mid = mido.MidiFile()

out_track = mido.MidiTrack()

out_mid.tracks.append(out_track)

# 收集音符事件及其绝对时间

events = []

current_time = 0

for msg in mid:

current_time += msg.time

if msg.type in ['note_on', 'note_off']:

events.append((current_time, msg))

# 反转事件时间

reversed_events = []

for time, msg in events:

new_time = total_length - time

reversed_events.append((new_time, msg))

# 按新的时间排序事件

reversed_events.sort(key=lambda x: x[0])

# 重建消息并更新时间

last_time = 0

for time, msg in reversed_events:

delta_time = time - last_time

msg.time = delta_time

out_track.append(msg)

last_time = time

# 保存反转后的 MIDI 文件

out_mid.save('output.mid')


最好的门神
XP 8432
最好的门神
回答于 2024/9/23 上午10:19
0

@农药君

https://github.com/mido/mido/issues/189https://github.com/mido/mido/issues/189

https://mido.readthedocs.io/en/1.1.24/midi_files.html

关于时间属性

时间属性有多种不同的使用方式:

在轨道内,它是以刻度为单位的增量时间。这必须是一个整数。

在 play() 生成的消息中,它是以秒为单位的增量时间(自上次生成消息以来经过的时间)

(仅对实现者重要)在某些方法中,它用于以滴答声或秒为单位的绝对时间

你把事件的事件属性想办法整成整数倍的刻度

最好的门神
XP 8432
最好的门神
回答于 2024/9/24 下午2:28
0

@农药君

我修正了最好的门神给出的python代码,请过目。

import mido


mid = mido.MidiFile('input.mid')


total_length = sum(msg.time for msg in mid if not msg.is_meta)


out_mid = mido.MidiFile()

out_track = mido.MidiTrack()

out_mid.tracks.append(out_track)


events = []

current_time = 0


for msg in mid:

    current_time += msg.time

    if not msg.is_meta and msg.type in ['note_on', 'note_off']:

        events.append((current_time, msg))


reversed_events = []

for time, msg in events:

    new_time = int(total_length - time) 

    reversed_events.append((new_time, msg))


reversed_events.sort(key=lambda x: x[0])


last_time = 0

for time, msg in reversed_events:

    delta_time = int(time - last_time) 

    new_msg = msg.copy(time=delta_time) 

    out_track.append(new_msg)

    last_time = time


out_mid.save('output.mid')

修正后,应该可以避免报错。

回答于 2024/9/23 下午9:32
  此条已删除  
0

@最好的门神 不是,你这个报错了啊


Traceback (most recent call last):

File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in

start(fakepyfile,mainpyfile)

File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start

exec(open(mainpyfile).read(), __main__.__dict__)

File "", line 40, in

File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/mido/midifiles/midifiles.py", line 458, in save

self._save(file)

File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/mido/midifiles/midifiles.py", line 471, in _save

write_track(outfile, track)

File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.11/site-packages/mido/midifiles/midifiles.py", line 244, in write_track

raise ValueError('message time must be int in MIDI file')

ValueError: message time must be int in MIDI file

[Program finished]

农药君
XP 120
农药君
回答于 2024/9/23 下午9:04
0

@最好的门神 问个问题,你给的那个是Python脚本吗?

如果是Python脚本那就好办,我有那个Pydroid 3,安卓端的Python编译器/解释器,我回头去看看有没有那个库

农药君
XP 120
农药君
回答于 2024/9/23 下午8:43
0

省流:打回重做(把midi触发的音符信号全部倒过来重新写过)


你描述的这个东西,就算有电脑,他也得手动一个一个的生抠过去。

这不就讲废话。

ChirSnier
XP 2365
ChirSnier
回答于 2024/9/22 下午9:44

您的回答

登录以回答

这儿是 MidiShow 问答区,欢迎您请教或帮大家解决关于音乐创作、MIDI 应用、MIDI 技术等音乐相关的问题。

问答区积分规则如下:


  1. 提问、回答或自问自答积分均不变
  2. 问题被赞成 : +10
  3. 问题被反对 : 提问者 -2,点击反对者不扣分
  4. 回答被赞成 : +10
  5. 回答被反对 : 回答者 -2,点击反对者 -1
  6. 提问者选出满意回答 :回答者 +15 ,提问者 +2

参与问答前请阅读:问答区玩法规则