Xamarin Getting Started翻译系列九--操作音频

操作音频

概述

现代的移动设备集成了一些特殊功能的部件摄像头、音乐播放器和视频录像器。因此,多媒体框架成为了移动API的第一大特性。

Android对多媒体提供了大量的支持。本文讲述在Android中操作音频,包含如下方面:

1.      使用MediaPlayer播放音频使用内置的MediaPlayer类播放音频,包括本地文件和使用AudioTrack播放流音频文件。

2.      录制音频使用内置的MediaRecorder类录制音频。

3.      处理音频通知使用音频通知,确保应用程序更加合理的处理请求事件,如当有电话打进来,停止或挂起音频输出。

4.      处理低层次音频使用AndioTrack类直接写内存缓冲区来播放音频。录制音频用AudioRecord类直接读取内存缓冲区。

Modern mobile devices have adopted functionality that formerly would have required dedicated pieces of equipment - cameras, musicplayers and video recorders. Because of this, multimedia frameworks have becomea first-class feature in mobile APIs.

 

Android provides extensive support for multimedia. This articleexamines working with audio in Android, and covers the following topics

 

1. Playing Audiowith MediaPlayer – Using thebuilt-in MediaPlayer class to play audio, including local audio files and streamed audio files with the AudioTrack class.

2. RecordingAudio – Using the built-in MediaRecorder class to record audio.

3. Working withAudio Notifications – Using audio notifications to create well-behavedapplications that respond correctlyto events (such as incoming phone calls) by suspending or canceling their audio outputs.

4. Working withLow-Level Audio – Playing audiousing the AudioTrack class by writing directly to memory buffers. Recordingaudio using the AudioRecord class and reading directly from memory buffers.

需求

本教程范例需要Android2.0(API5)或更高版本。

注意必须在Android设备上调试音频。

必须在AndroidManifest.XML文件中开放RECORD_AUDIO许可。

This guide requires Android 2.0 (API level 5) or higher.

Please note that debugging audio on Android must be doneon a device.

It is necessary to request the RECORD_AUDIO permissionsin AndroidManifest.XML:


使用MediaPlayer 类播放音频

最简单播放音频的方式是使用内置的MediaPlayer类。MediaPlayer可通过文件路径播放本地货远程音频文件。然而,MediaPlayer是状态敏感的,在错误的状态下调用其函数会抛出异常。需要使用下面描述的方式操作MediaPlayer才能避免错误。

The simplest way to play audio in Android is with thebuilt-in MediaPlayer class. MediaPlayer can playeither local or remote files by passing in the file path. However, MediaPlayer is very state sensitive and calling one of its methods inthe wrong state will cause an exception to be thrown. It’s important tointeract with MediaPlayer in the order described below to avoid errors.

初始化和播放

使用MediaPlayer播放音频需要如下步骤:

1.        实例化一个MediaPlayer对象

2.        使用SetDataSource方法设置要播放的文件

3.        调用Prepare方法初始化播放器

4.        调用Start方法开始播放

范例代码如下:

Playing audio with MediaPlayer requires the following sequence:

 

1. Instantiate a new MediaPlayer object.

 

2. Configure the fileto play via the SetDataSource method.

 

3. Call the Prepare method toinitialize the player.

 

4. Call the Start method tostart the audio playing. The code sample below illustrates this usage:

protected MediaPlayer player;

 

public void StartPlayer(String  filePath)

 

{

 

if (player == null) {

player = new MediaPlayer();

} else { player.Reset();player.SetDataSource(filePath); player.Prepare(); player.Start();

 

}

 

}

 

 

停止或恢复播放

调用Pause暂停播放:

The playback can be suspended by calling the Pause method: player.Pause();

要继续暂停的播放,调用Start方法。将从暂停的地方继续播放:

To resume paused playback, call the Start method. This will resume from the paused location in theplayback:

 

player.Start();

 

 

调用播放器的Stop方法停止播放:

Calling the Stop method on the player ends an ongoingplayback:

 

 

player.Stop();

 

 

用完播放器必须释放资源:

When the player is no longer needed, the resources must bereleased:

 

 

player.Release();

 

 

 

使用MediaRecorder 类录音

Android中录制音频使用MediaRecorder类。同MediaPlayer一样,也是状态敏感的,要进行录音必须经过几个状态的转换。

要录音必须开启RECORD_AUDIO许可。

如何设置应用程序许可见Working with the AndroidManifest guide

The corollary to MediaPlayer for recording audio in Android is the MediaRecorder class. Likethe MediaPlayer, it is state-sensitive and transitions through several statesin order to get to the point where it can start recording.

 

In order to record audio, the RECORD_AUDIO permission must be set

 

 

For instructions on how to set application permissions seethe Working with the Android

 

Manifest guide.

 

 

初始化并录音

使用MediaRecorder录制音频必须有如下几步:

1.        实例化MediaRecorder对象

2.        使用SetAudioSource方法指定捕获音频输入的硬件设备

3.        使用SetOutputFormat函数设置音频输出格式。支持的音频类型见Android Supported Media Formats

4.        调用SetAudioEncoder方法设置音频编码

5.        调用SetOutputFile方法指定要保存音频数据的目标文件。

6.        调用Prepare初始化录音器

7.        调用Start方法开始录音

范例代码如下:

Recording audio with theMediaRecorder requires the following steps:

 

 

1. Instantiate a new MediaRecorder object.

 

2. Specify which hardwaredevice to use to capture the audio input via the

 

SetAudioSource method.

 

3. Set the output fileaudio format using the SetOutputFormat method. For a list of supported audio types see Android Supported Media Formats.

4. Call the SetAudioEncoder method to setthe audio encoding type.

 

5. Call the SetOutputFile method tospecify the name of the output filethat the audio data is written to.

6. Call the Prepare method toinitialize the recorder.

 

7. Call the Start method tostart recording.

 

 

The following code sample illustrates this sequence:

 

 

protected MediaRecorder recorder;

 

void RecordAudio (String filePath)

 

{

 

try {

if (File.Exists (filePath)) { File.Delete(filePath);

 

}

 

if (recorder == null) {

 

recorder = new MediaRecorder (); // Initial state.

 

} else {

 

recorder.Reset ();

recorder.SetAudioSource (AudioSource.Mic);recorder.SetOutputFormat (OutputFormat.ThreeGpp); recorder.SetAudioEncoder(AudioEncoder.AmrNb);

// Initialized state. recorder.SetOutputFile (filePath);

// DataSourceConfigured state. recorder.Prepare (); // Preparedstate recorder.Start (); // Recording state.

}

} catch (Exception ex) { Console.Out.WriteLine(ex.StackTrace);

 

}

 

}

 

停止录音

调用MediaRecorderStop方法停止录音:

To stop the recording, call the Stop method on the MediaRecorder:

 

 

recorder.Stop();

 

清理

停止MediaRecorder后,调用Reset方法将其置于空闲状态:

Once the MediaRecorder has beenstopped, call the Reset method to putit back into its idle state:

 

recorder.Reset();

 

用完MediaRecorder,释放资源:

When the MediaRecorder is no longerneeded, its resources must be released:

 

 

recorder.Release();

 

 

 

管理音频通知

AudioManager 类

AudioManager类为处理音频通知提供途径,应用程序可以处理音频事件。这个服务还提供了其他音频特性,如音量和铃声类型控制。AudioManager使应用程序可以处理音频通知,控制音频播放。

The AudioManager classprovides access to audio notifications that let applications know when audioevents occur. This service also provides access to other audio features, suchas volume and ringer mode control. The AudioManager allows an application to handle audio notifications tocontrol audio playback.

 

管理音频焦点

设备的音频资源—内置播放器和录音器,由所有运行中的应用程序共享。

概念上与PC机中只有一个应用程序可以获取键盘焦点相类似:选择一个运行中的应用程序并点击,则只能对这个应用程序进行键盘输入。

音频焦点的思路也是这样的,避免多个应用程序同时播放或录音。这比键盘焦点更复杂,因为是自发管理的(应用程序可能忽略当前它没有一音频焦点的事实而直接播放)、可能需要不同类型的音频焦点。例如,请求者只想播放很短的音频,可能会请求临时的焦点。

The audio resources of the device - the built-in playerand recorder - are shared by all running applications.

 

Conceptually, this is similar toapplications on a PC where only one application has the keyboard focus: afterselecting one of the running applications by mouse-clicking it, the keyboardinput goes only to that application.

 

Audio focus is a similar idea and prevents more than oneapplication from playing or recording audio at the same time. It is morecomplicated than keyboard focus because it is voluntary - the application canignore that fact that it does not currently have audio focus and play regardless- and because there are different types of audio focus that can be requested.For example, if the requestor is only expected to play audio for a very shorttime, it may request transient focus.

 

音频焦点可能会理解获得,也可能拒绝或稍后才获取到。例如,一个应用程序在电话通话中请求音频焦点,将会被拒绝,但当通话结束后可能会得到音频焦点。这时,需要注册一个侦听器来处理失去音频焦点的情况。请求音频焦点通常可用来检查播放或录音是否结束。

关于音频焦点的更多信息见Android Audio Focus document

Audio focus may be granted immediately, or initiallydenied and granted later. For example, if an application requests audio focusduring a phone call, it will be denied, but focus may well be granted once thephone call is finished. In this case, a listener is registered in order torespond accordingly if audio focus is taken away. Requesting audio focus isused to determine whether or not it is OK to play or record audio.

 

For more information about audio focus, see the Android Audio Focus document.

 

 

为音频焦点注册回调函数

IOnAudioChangeListener接口中注册FocusChangeListener回调函数对于获取和是否音频焦点是很重要的。因为请求的音频焦点可能会延迟一段时间才能被授权。例如,当电话通话的时候应用程序请求播放音乐。音频焦点会在电话结束后才能获取到。

因此在AudioManager的GetAudioFocus方法中传递一个回调对象作为参数。如果音频焦点被拒绝,稍后才被允许,将调用回调对象的OnAudioFocusChange方法通知应用程序。同样的方法告诉应用程序已经失去音频焦点。

Registeringthe FocusChangeListener callback from the IOnAudioChangeListener is

an important part of obtaining and releasing audio focus.This is because the granting of audio focus may be deferred until a later time.For example, an application may request to play music while there is a phonecall in progress. Audio focus will not be granted until the phone call isfinished.

 

For this reason, the callback object is passed as a parameterinto the GetAudioFocus method of the AudioManager, and it is this call that registers the callback. Ifaudio focus is initially denied but later granted, the application is informedby invoking OnAudioFocusChange on thecallback. The same method is used to tell the application that audio focus isbeing taken away.

当应用程序使用完音频资源,调用AudioManager的AbandonFocus方法,又一次触发回调。这时会注销回调并释放音频资源,让其他应用程序获取音频焦点。

When the application has finished using the audioresources, it calls the AbandonFocus method of the AudioManager, and again passes in thecallback. This deregisters the callback and releases the audio resources, sothat other applications may obtain audio focus.

请求音频焦点

请求设备上的音频资源的步骤:

1.        获取AudioManager系统服务实例

2.        创建回调类型实例

3.        调用AudioManagerRequestAudioFocus方法请求设备的音频资源。方法参数是回调对象、流类型(音乐、语音电话、铃声等等)、请求的权限类型(例如,立刻请求音频资源或无限期等待)

4.        如果请求被准许,立刻调用playMusic方法,开始播放音频

5.        如果请求被拒绝,不能继续执行。这时,音频只能在请求被准许的时候才能执行。

范例代码如下:

The steps required to request the audio resources of thedevice are as follow:

 

 

1. Obtain a handle tothe AudioManager system service.

 

2. Create an instanceof the callback class.

 

3. Request the audioresources of the device by calling the RequestAudioFocus method on theAudioManager. The parameters are the callback object, the stream type(music, voice call, ring etc.) andthe type of the access right being requested (the audio resources can be requested momentarily or for anindefinite period, for example).

4. If the request isgranted, the playMusic method is invoked immediately, and the audio starts toplay back.

5. If the request isdenied, no further action is taken. In this case, the audio will only play if the request is granted at a later time.

 

The code sample below shows these steps:

Boolean RequestAudioResources(INotificationReceiver parent)

 

{

 

AudioManager audioMan = (AudioManager)GetSystemService(Context.AudioService);

AudioManager.IOnAudioFocusChangeListener listener = new

 

MyAudioListener(this);

 

var ret = audioMan.RequestAudioFocus (listener,Stream.Music, AudioFocus.Gain );

if (ret == AudioFocusRequest.Granted) {

 

playMusic();

 

return (true);

 

} else if (ret == AudioFocusRequest.Failed) {

 

return(false);

 

}

 

return (false);

 

}

 

 

释放音频焦点

当完成音频播放,调用AudioManagerAbandonFocus方法。使其他应用程序可以获取设备的音频资源。如果其他应用程序注册了监听器则会收到音频焦点变化的通知。

When the playback of the track is complete, the AbandonFocus method on AudioManager is invoked. This allows anotherapplication to gain the audio resources of the device. Other applications willreceive a notification of this audio focus change if they have registered theirown listeners.

 

 

底层音频 API

底层音频API可以更灵活的控制音频播放盒录制,因此可以直接操作内存缓冲区,而不是文件的URI。有些情况比较适合使用:

1.        播放加密的音频文件

2.        播放一连串的语音片段

3.        音频流

The low-level audio APIs provide a greater control overaudio playing and recording because they interact directly with memory buffersinstead of using file URIs. There are some scenarios where this approach ispreferable. Such scenarios include:

 

1. When playing fromencrypted audio files.

 

2. When playing asuccession of short clips.

 

3. Audio streaming.

 

 

AudioTrack 类

AudioTrack类是底层的播放API,等同于MediaPlayer。

The AudioTrack class usesthe low-level audio APIs for recording, and is the low-level equivalent of the MediaPlayer class.

 

初始化和播放

为了播放音频,需要实例化一个AudioTrack类。构造函数参数如下所示,指定音频采用等信息:

1.        流类型—语音、铃声、音乐、系统或闹铃

2.        频率—采样频率—Hz

3.        频道配置—单声道或立体声

4.        音频格式—8位或16位编码

5.        缓冲区大小—字节

6.        缓冲区模式—流或静态

构造实例后调用AudioTrack的Play方法,开始播放。将音频缓冲区写入AudioTrack中开始播放:

In order to play audio, a new instance of AudioTrack must be instantiated. The argument list passed into theconstructor specifies how to play the audio sample contained in the buffer. Thearguments are:

 

1. Stream type –Voice, ringtone, music, system or alarm.

 

2. Frequency – Thesampling rate expressed in Hz.

 

3. ChannelConfiguration – Mono or stereo.

 

4. Audio format – 8bit or 16 bit encoding.

 

5. Buffer size – inbytes.

 

6. Buffer mode –streaming or static.

 

 

After construction, the Play method of AudioTrack is invoked,to set it up to start playing. Writing the audio buffer to the AudioTrack starts the playback:

 

 

 

void PlayAudioTrack(byte[] audioBuffer)

 

{

 

AudioTrack audioTrack = new AudioTrack(

 

// Stream type

 

Stream.Music,

 

// Frequency

 

11025,

 

// Mono or stereo

 

ChannelConfiguration.Mono,

 

// Audio encoding

 

Android.Media.Encoding.Pcm16bit,

// Length of the audio clip. audioBuffer.Length,

// Mode. Stream or static.

 

AudioTrackMode.Stream);

 

 

 

audioTrack.Play();

 

audioTrack.Write(audioBuffer, 0, audioBuffer.Length);

 

}

 

 

暂停、停止播放

调用Pause方法暂停播放:

Call the Pause method to pause theplayback: audioTrack.Pause();

调用Stop方法停止播放:

Calling the Stop method will terminate the playbackpermanently:

 

 

audioTrack.Stop();

 

 

清理

当AudioTrack实例工作完毕,需要释放资源:

When the AudioTrack is no longer needed, its resourcesmust be released:

 

 

audioTrack.Release();

 

 

AudioRecord 类

AudioRecord是与AudioTrack同等级的。直接使用内存缓冲区替代文件盒URI。需要在清单中设置RECORD_AUDIO许可。

The AudioRecord class is theequivalent of AudioTrack on therecording side. Like AudioTrack, it uses memory buffers directly, in place offiles and URIs. It requires that the RECORD_AUDIO permission be set in themanifest.

 

初始化和录音

首先实例化AudioRecord对象。构造函数的参数提供录制必要的信息。与AudioTrack的参数多是枚举不同,AudioRecord对应的参数都是整形。包括:

1.        音频音频输入源,如麦克风

2.        流类型—语音、铃声、音乐、系统或闹铃

3.        频率—采样频率(Hz)

4.        通道配置—单声道或立体声

5.        音频格式—8位或16位编码

6.        缓冲区大小—字节

The first step is to construct a new AudioRecord object. Theargument list passed into the constructor provides all the information requiredfor recording. Unlike in AudioTrack, where the arguments are largely enumerations, the equivalentarguments in AudioRecord are integers. These include:

 

1. Hardware audioinput source such as microphone.

 

2. Stream type –Voice, ringtone, music, system or alarm.

 

3. Frequency – Thesampling rate expressed in Hz.

 

4. ChannelConfiguration – Mono or stereo.

 

5. Audio format – 8bit or 16 bit encoding.

 

6. Buffer size-inbytes

AudioRecord创建后,调用StartRecording方法,开始录制。AudioRecord不断从输入缓冲区中读取数据写入到输出音频文件中。

Once the AudioRecord is constructed, its StartRecording method is invoked. It is now ready to begin recording. TheAudioRecord continuously reads the audio buffer for input, and writesthis input out to an audio file.

 

void RecordAudio()

 

{

 

byte[] audioBuffer = new byte[100000];

 

var audRecorder = new AudioRecord(

 

// Hardware source of recording. AudioSource.Mic,

// Frequency

 

11025,

 

// Mono or stereo

 

ChannelConfiguration.Mono,

 

// Audio encoding

 

Android.Media.Encoding.Pcm16bit,

// Length of the audio clip. audioBuffer.Length

 

); audRecorder.StartRecording(); for while (true) {

try

 

{

// Keep reading the buffer while there is audio input.audRecorder.Read(audioBuffer, 0, audioBuffer.Length);

// Write out the audio file.

} catch (Exception ex) { Console.Out.WriteLine(ex.Message);break;

 

}

 

}

 

}

 

 

停止录音

调用Stop方法停止录制:

Calling the Stop method terminates the recording:

 

 

audRecorder.Stop();

 

 

清理

当不在需要AudioRecord对象,调用Release方法释放与之相关的资源:

When the AudioRecord object is nolonger needed, calling its Release method releases all resources associated with it:

 

audRecorder.Release();

 

 

 

汇总

Android系统提供了强大的框架来播放、录制和管理音频。本文讨论了如何使用高级别的MediaPlayer和MediaRecorder类播放和录制音频。接着讲述如何使用音频通知使音频资源在多个应用程序间共享。最后,阐述了使用底层API直接操作内存缓冲区来播放和录制音频。

The Android OS provides a powerfulframework for playing, recording and managing audio. This article covered howto play and record audio using the high-level MediaPlayer and MediaRecorder classes. Next, it explored how to use audio notificationsin order to share the audio resources of the device between differentapplications. Finally, it dealt with how to playback and record audio using thelow-level APIs, which interface directly with memory buffers.


阅读更多
个人分类: Xamarin
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭