unity播放加密的音频文件

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

1.NAudio的链接:http://naudio.codeplex.com/,里面有相关的介绍和详细的文档,对unity3d还有一个插件,https://www.assetstore.unity3d.com/en/#!/content/32034 ,我并没有机会下载下来学习一下,只是简单使用了NAudio的几个接口,后面有兴趣的可以和我一起研究一下NAudio。
2.NVorbis的链接: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 
  4.1 使用命名空间

1
2
using NAudio;
using NAudio.Wave;
  4.2 申请一个播放组件和一个音频文件读取
1
2
IWavePlayer waveOutDevice;
AudioFileReader audioFileReader;
  4.3 开始读取文件和播放音乐
1
2
3
4
5
6
void Start (){
         waveOutDevice = new WaveOut();
         audioFileReader = new AudioFileReader( @"D:\影音文件\音乐\BEYOND\黄家驹 - 总有爱.mp3" );
         waveOutDevice.Init(audioFileReader);
         waveOutDevice.Play();
     }
  4.4 注意在程序中退出的关闭音乐播放组件,因为他并不是使用unity在播放声音,而且使用自带的组件播放的了
1
2
3
4
5
6
7
8
9
10
11
12
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  ,我这里还是会使用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
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;
        }
    }
 
    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 
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
         }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值