NAudio来处理MP3和wav的音频

首先说一下起因,我这里有需求将音频文件加密,所以一般的组件和www加载都不能使用,于是我需要一种新的方案来加载音频文件。于是我找到了一个开源的音频处理类库NAudio来处理MP3和wav的音频文件,同时我还需要使用到ogg的音频格式,后面还找到了NVorbis,我这里也是初步探索,顺便发篇博客分享一下。

1.NAudio的链接:[http://naudio.codeplex.com/](javascript:void() "http://naudio.codeplex.com/"),里面有相关的介绍和详细的文档,对unity3d还有一个插件,[https://www.assetstore.unity3d.com/en/#!/content/32034](javascript:void() "https://www.assetstore.unity3d.com/en/#!/content/32034 ") ,我并没有机会下载下来学习一下,只是简单使用了NAudio的几个接口,后面有兴趣的可以和我一起研究一下NAudio。
2.NVorbis的链接:[http://nvorbis.codeplex.com/](javascript:void() "http://nvorbis.codeplex.com/ ") ,这里是支持ogg需要下载的类库,后面我实用到相关的接口,我再给出详细的文档链接。
3.从NAudio和NVorbis下载发布的dll文件放在unity中,NVorbis还需要导入NVorbis.NAudioSupport.dll后面需要使用NAudio来播放ogg,记得将unity的Api Compatibility Level 改为.NET 2.0。
4.在unity3d中播放MP3,文档链接[http://naudio.codeplex.com/wikipage?title=MP3](javascript:void() "http://naudio.codeplex.com/wikipage?title=MP3 ")
4.1 使用命名空间

using

NAudio;

using

NAudio.Wave;

4.2 申请一个播放组件和一个音频文件读取
IWavePlayer waveOutDevice;`

AudioFileReader audioFileReader;`

|

4.3 开始读取文件和播放音乐

void

Start (){

waveOutDevice = new

WaveOut();

audioFileReader = new

AudioFileReader(

@"D:\影音文件\音乐\BEYOND\黄家驹 - 总有爱.mp3"

);

waveOutDevice.Init(audioFileReader);

waveOutDevice.Play();

}

|

4.4 注意在程序中退出的关闭音乐播放组件,因为他并不是使用unity在播放声音,而且使用自带的组件播放的了

void

OnApplicationQuit()

{

if

(waveOutDevice != null

)

{

waveOutDevice.Stop();

}

if

(waveOutDevice != null

)

{

waveOutDevice.Dispose();

waveOutDevice = null

;

}

}

|

4.5 还有这里加载wav也是同样可以播放的,同时应该也可以试试其他格式的音频比如aiff,但是肯定不支持ogg,下面我会单独再来使用ogg。

5.在unity3d中播放ogg,文档链接:

[http://nvorbis.codeplex.com/documentation](javascript:void() "http://nvorbis.codeplex.com/documentation ")

,我这里还是会使用NAudio来播放

5.1使用命名空间

|

1

2

|

using

NVorbis;

using

NVorbis.NAudioSupport;

|

5.2 加载ogg文件,并开始播放

|

1

2

3

4

5

6

|

void

Start (){

waveOutDevice = new

WaveOut();

VorbisWaveReader oggReader = new

VorbisWaveReader(

@"D:\侧田 - 感动.ogg"

);

waveOutDevice.Init(oggReader);

waveOutDevice.Play();

}

|

6.按着以上的方法来播放音乐是否感觉特别简单了,但是在实际使用中,如果是加载外部音频文件,我知道肯定有人还是觉得使用www来加载感觉更方便一些。

于是我决定再来啰嗦一下,如果使用www外部加载时不能加载MP3格式的音频文件,但是目前MP3格式的音频文件确实最多的,还有一个重要因素是,我目前解密出来的音频文件是一堆字节数组,而且我也不知道不同音频应该怎样去解码,如果我再把字节数组去写成一个音频文件再用www来读取,那确实有点闲得蛋疼的感觉了。

于是下面就是来实现怎样利用NAudio和NVorbis把一堆字节数组转成unity的AudioClip,使用unity的AudioSource来播放。

6.1 mp3/wav字节数组转AudioClip,具体给出代码来了,参考链接:

[http://gamedev.stackexchange.com/questions/114885/how-do-i-play-mp3-files-in-unity-standalone](javascript:void() "http://gamedev.stackexchange.com/questions/114885/how-do-i-play-mp3-files-in-unity-standalone")

|

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

|

public

static

AudioClip FromWavData(

byte

[] data)

{

// Load the data into a stream

MemoryStream wavstream = new

MemoryStream(data);

WaveFileReader wavaudio = new

WaveFileReader(wavstream);

WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(wavaudio);

// Convert to WAV data

WAV wav = new

WAV(AudioMemStream(waveStream).ToArray());

Debug.Log(wav);

AudioClip audioClip = AudioClip.Create(

"clip"

, wav.SampleCount, 1, wav.Frequency, false

);

audioClip.SetData(wav.LeftChannel, 0);

// Return the clip

return

audioClip;

}

public

static

AudioClip FromMp3Data(

byte

[] data)

{

// Load the data into a stream

MemoryStream mp3stream = new

MemoryStream(data);

// Convert the data in the stream to WAV format

Mp3FileReader mp3audio = new

Mp3FileReader(mp3stream);

WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(mp3audio);

// Convert to WAV data

WAV wav = new

WAV(AudioMemStream(waveStream).ToArray());

Debug.Log(wav);

AudioClip audioClip = AudioClip.Create(

"clip"

, wav.SampleCount, 1, wav.Frequency, false

);

audioClip.SetData(wav.LeftChannel, 0);

// Return the clip

return

audioClip;

}

private

static

MemoryStream AudioMemStream(WaveStream waveStream)

{

MemoryStream outputStream = new

MemoryStream();

using

(WaveFileWriter waveFileWriter = new

WaveFileWriter(outputStream, waveStream.WaveFormat))

{

byte

[] bytes = new

byte

[waveStream.Length];

waveStream.Position = 0;

waveStream.Read(bytes, 0, Convert.ToInt32(waveStream.Length));

waveFileWriter.Write(bytes, 0, bytes.Length);

waveFileWriter.Flush();

}

return

outputStream;

}

}

`/* From

[http://answers.unity3d.com/questions/737002/wav-byte-to-audioclip.html](javascript:void() "http://answers.unity3d.com/questions/737002/wav-byte-to-audioclip.html")

*/`

public

class

WAV

{

// convert two bytes to one float in the range -1 to 1

static

float

bytesToFloat(

byte

firstByte, byte

secondByte)

{

// convert two bytes to one short (little endian)

short

s = (

short

)((secondByte << 8) | firstByte);

// convert to range from -1 to (just below) 1

return

s / 32768.0F;

}

static

int

bytesToInt(

byte

[] bytes, int

offset = 0)

{

int

value = 0;

for

(

int

i = 0; i < 4; i++)

{

value |= ((

int

)bytes[offset + i]) << (i * 8);

}

return

value;

}

// properties

public

float

[] LeftChannel { get

; internal

set

; }

public

float

[] RightChannel { get

; internal

set

; }

public

int

ChannelCount { get

; internal

set

; }

public

int

SampleCount { get

; internal

set

; }

public

int

Frequency { get

; internal

set

; }

public

WAV(

byte

[] wav)

{

// Determine if mono or stereo

ChannelCount = wav[22]; ``// Forget byte 23 as 99.999% of WAVs are 1 or 2 channels

// Get the frequency

Frequency = bytesToInt(wav, 24);

// Get past all the other sub chunks to get to the data subchunk:

int

pos = 12; ``// First Subchunk ID from 12 to 16

// Keep iterating until we find the data chunk (i.e. 64 61 74 61 ...... (i.e. 100 97 116 97 in decimal))

while

(!(wav[pos] == 100 && wav[pos + 1] == 97 && wav[pos + 2] == 116 && wav[pos + 3] == 97))

{

pos += 4;

int

chunkSize = wav[pos] + wav[pos + 1] * 256 + wav[pos + 2] * 65536 + wav[pos + 3] * 16777216;

pos += 4 + chunkSize;

}

pos += 8;

// Pos is now positioned to start of actual sound data.

SampleCount = (wav.Length - pos) / 2; ``// 2 bytes per sample (16 bit sound mono)

if

(ChannelCount == 2) SampleCount /= 2; ``// 4 bytes per sample (16 bit stereo)

// Allocate memory (right will be null if only mono sound)

LeftChannel = new

float

[SampleCount];

if

(ChannelCount == 2) RightChannel = new

float

[SampleCount];

else

RightChannel = null

;

// Write to double array/s:

int

i = 0;

while

(pos < wav.Length)

{

LeftChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);

pos += 2;

if

(ChannelCount == 2)

{

RightChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);

pos += 2;

}

i++;

}

}

public

override

string

ToString()

{

return

string

.Format(

"[WAV: LeftChannel={0}, RightChannel={1}, ChannelCount={2}, SampleCount={3}, Frequency={4}]"

, LeftChannel, RightChannel, ChannelCount, SampleCount, Frequency);

}

|

6.2 ogg字节数组转AudioClip,参考链接:

[http://answers.unity3d.com/questions/499028/onaudioread-buffer-changing-sizes.html](javascript:void() "http://answers.unity3d.com/questions/499028/onaudioread-buffer-changing-sizes.html ")

|

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

|

static

NVorbis.VorbisReader vorbis;

public

static

AudioClip FromOggData(

byte

[] data)

{

// Load the data into a stream

MemoryStream oggstream = new

MemoryStream(data);

vorbis = new

NVorbis.VorbisReader(oggstream, false

);

int

samplecount = (

int

)(vorbis.SampleRate * vorbis.TotalTime.TotalSeconds);

AudioClip audioClip = AudioClip.Create(

"clip"

, samplecount, vorbis.Channels, vorbis.SampleRate, false

, true

, OnAudioRead, OnAudioSetPosition);

// Return the clip

return

audioClip;

}

static

void

OnAudioRead(

float

[] data)

{

var f = new

float

[data.Length];

vorbis.ReadSamples(f, 0, data.Length);

for

(

int

i = 0; i < data.Length; i++)

{

data[i] = f[i];

}

}

static

void

OnAudioSetPosition(

int

newPosition)

{

vorbis.DecodedTime = new

TimeSpan(0);``//Only used to rewind the stream, we won't be seeking

}

|

7.这里我给出了很多的相关链接,都是我在查找NAudio的资料,对我使用有帮助的一些文章,也分享给大家一起学习。而且NAudio好像还支持读取midi文件与合并mp3等很多功能,可以持续关注。

你可能感兴趣的:(NAudio来处理MP3和wav的音频)