如何为 Android (Java) 编写一个简单的音乐音序器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7823619/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to program a simple music sequencer for Android (Java)
提问by caw
What I want to do:
我想做的事:
I would like to program a very simple music sequencer for Android. But I've never worked with audio on Android or in Java, respectively.
我想为 Android 编写一个非常简单的音乐音序器。但我从未分别在 Android 或 Java 上使用过音频。
What the application should do:
应用程序应该做什么:
- play back samples (WAVE/OGG files)
- play several audio channels simultaneously (e.g. the trumpet and the flute should play simultaneously, maximum of 10 instruments)
- change the pitch of the samples (e.g. the trumpet WAVE file must be played in normal pitch (c4) and lower/higher pitch (e2/g6) and so on)
- 回放样本(WAVE/OGG 文件)
- 同时播放多个音频通道(例如,小号和长笛应同时播放,最多 10 种乐器)
- 更改样本的音高(例如,小号 WAVE 文件必须以正常音高 (c4) 和较低/较高音高 (e2/g6) 等播放)
This is what the application should be able to do in general.
这是应用程序通常应该能够做到的。
What components do I need? A normal media player (AudioManager?) won't work, right?
我需要哪些组件?普通的媒体播放器(AudioManager?)不起作用,对吧?
There are already some applications which do what I am thinking about:
已经有一些应用程序可以做我正在考虑的事情:
- FingerBeat for iOS
- FL Studio Mobile for iOS
- Uloops Studio for Android
- 适用于 iOS 的 FingerBeat
- 适用于 iOS 的 FL Studio 移动版
- 安卓版 Uloops Studio
Thanks in advance for your help!
在此先感谢您的帮助!
采纳答案by Lycha
回答by Durandal
You have not one simple requirement, but three very different requirements.
您没有一个简单的要求,而是三个截然不同的要求。
Playing WAV should be supported out of the box by the JRE with the help of the classes in javax.sound.sampled, it jsut requires some code to wire it up (not too sure about android).
Playing OGG is not supported out of the box. There is an open source implementation for OGG called jOrbis, see their web site. Again this can require some wiring code to hook into your application.
For a Sequencer, you could just use MIDI. Again it should be supported by the JRE, and if it is not on your platform, you can use Gervill - a pure Java MIDI sequencer (Project web site).
There is also a ModPlayer that can play good old Soundtracker and some others. This can also be abused as a Sequencer of some sort if you know the Soundtracker or Screamtracker module format (ancient format, but descriptions are still available on the net). Player with source can be found here. The Tracker formats are not all that ancient by the way, some of todays game engines still make use of them.
If you really want, you can cook up your own Sequencer, all the basic stuff if there in javax.sound.sampled. It just requires some basic knowledge about digital sound and a big lot of wiring code.
JRE 应该在 javax.sound.sampled 中的类的帮助下开箱即用地支持播放 WAV,它需要一些代码来连接它(对 android 不太确定)。
开箱即用不支持播放 OGG。OGG 有一个名为 jOrbis 的开源实现,请参阅他们的网站。同样,这可能需要一些接线代码才能连接到您的应用程序中。
对于音序器,您可以只使用 MIDI。同样,它应该得到 JRE 的支持,如果它不在您的平台上,您可以使用 Gervill——一个纯 Java MIDI 音序器(项目网站)。
还有一个 ModPlayer 可以播放很好的旧 Soundtracker 和其他一些。如果您知道 Soundtracker 或 Screamtracker 模块格式(古老的格式,但网络上仍然提供描述),这也可能被用作某种音序器。可以在此处找到带有源的播放器。顺便说一下,Tracker 格式并不是那么古老,今天的一些游戏引擎仍在使用它们。
如果你真的想要,你可以编写你自己的 Sequencer,所有基本的东西,如果在 javax.sound.sampled 中有的话。它只需要一些关于数字声音的基本知识和大量的接线代码。
There is no single solution for allyour needs, you will have to stitch you own together from the building blocks freely available.
没有单一的解决方案可以满足您的所有需求,您必须从免费提供的构建块中拼接您自己的解决方案。
回答by Boude
I won't be able to provide a complete answer, but I will point you in the right direction.
我无法提供完整的答案,但我会为您指明正确的方向。
Android does support .wav and .ogg decoding. According to: http://developer.android.com/guide/appendix/media-formats.html
Android 确实支持 .wav 和 .ogg 解码。根据:http: //developer.android.com/guide/appendix/media-formats.html
I don't have any experience in audio, but your best bet seems to be the SoundPool class, it allows you to adjust pitch and volume and it seems to be able to play multiple sounds simultaneously: "Note that calling play() may cause another sound to stop playing if the maximum number of active streams is exceeded." http://developer.android.com/reference/android/media/SoundPool.html
我没有任何音频经验,但您最好的选择似乎是 SoundPool 类,它允许您调整音高和音量,并且似乎能够同时播放多个声音:“请注意,调用 play() 可能会导致如果超过最大活动流数,另一种声音将停止播放。” http://developer.android.com/reference/android/media/SoundPool.html
There also is a MediaPlayer class, but this is for more simple use. I don't think it allows pitch control.
还有一个 MediaPlayer 类,但这是为了更简单的使用。我认为它不允许音高控制。
回答by gadjou
I made something similar for my application (playing trombones sample). After a lot of experiencing, I found the best solution was to use AudioTrack. Have a look at my source code: http://code.google.com/p/trombonino/source/browse/trunk/src/com/trombonino
我为我的应用程序制作了类似的东西(播放长号示例)。经过多次体验,我发现最好的解决方案是使用AudioTrack。看看我的源代码:http: //code.google.com/p/trombonino/source/browse/trunk/src/com/trombonino
Especially
尤其
http://code.google.com/p/trombonino/source/browse/trunk/src/com/trombonino/Trombone.javahttp://code.google.com/p/trombonino/source/browse/trunk/src/com/trombonino/WavFile.java
http://code.google.com/p/trombonino/source/browse/trunk/src/com/trombonino/Trombone.javahttp://code.google.com/p/trombonino/source/browse/trunk/src /com/trombonino/WavFile.java
回答by JonasE
You will have problems with your timing on the Android system. To avoid your sequencer thread being interrupted by garbage collection you probably need to write the sequencer in native using the ndk.
您在 Android 系统上的计时会有问题。为了避免您的定序器线程被垃圾收集中断,您可能需要使用 ndk 在本机中编写定序器。
Playing back the sounds is probably best to do using the ndk as well.
播放声音最好也使用 ndk。
Take a look at https://code.google.com/p/high-performance-audio/
看看https://code.google.com/p/high-performance-audio/
In the above Soundfuse example the sequencer uses SystemClock.sleep() that is never a good idea. Check Why using System.Threading.Thread.Sleep() is a bad practice?.
在上面的 Soundfuse 示例中,音序器使用 SystemClock.sleep() 这从来都不是一个好主意。检查为什么使用 System.Threading.Thread.Sleep() 是不好的做法?.
Realized this question is really old but will answer it anyway since no answer mentions the NDK.
意识到这个问题真的很老了,但无论如何都会回答它,因为没有答案提到 NDK。