我想将我在 adobe air 中编写的应用程序移植到 xamarin。原因是我无法使用 flex 框架从 ipod 库中获取 mp3。现在我可以获取音频文件的列表,但我无法从资产中提取音频缓冲区。在 AS3 中,它是一个黑盒,但它始终将数据导出为具有以下属性的字节数组:
- 采样率 44100Hz
- 32 位
- 浮点
- 立体声
因为我不想重写所有算法,所以我想以与 AIR 中相同的格式“转换”所有歌曲。所以我写了这个
AVAsset urlAsset = AVUrlAsset.FromUrl (url);
NSError error = null;
AVAssetReader reader = new AVAssetReader (urlAsset, out error);
AVAssetTrack[] tracks = urlAsset.TracksWithMediaType (AVMediaType.Audio);
NSMutableDictionary audioReadSettings = new NSMutableDictionary ();
audioReadSettings.SetValueForKey (NSNumber.FromObject(AudioFormatType.LinearPCM), AVAudioSettings.AVFormatIDKey);
audioReadSettings.SetValueForKey (NSNumber.FromBoolean(false), AVAudioSettings.AVLinearPCMIsBigEndianKey);
audioReadSettings.SetValueForKey (NSNumber.FromBoolean(true), AVAudioSettings.AVLinearPCMIsFloatKey);
audioReadSettings.SetValueForKey (NSNumber.FromBoolean(false), AVAudioSettings.AVLinearPCMIsNonInterleaved);
audioReadSettings.SetValueForKey ((NSNumber)32, AVAudioSettings.AVLinearPCMBitDepthKey);
/*
audioReadSettings.SetValueForKey ((NSNumber)2, AVAudioSettings.AVNumberOfChannelsKey);
audioReadSettings.SetValueForKey ((NSNumber)44100.0, AVAudioSettings.AVSampleRateKey);
*/
AVAssetTrack track = tracks[0];
AVAssetReaderTrackOutput outputReader = AVAssetReaderTrackOutput.FromTrack (track, audioReadSettings);
if (!reader.CanAddOutput(outputReader)){
return;
}
reader.AddOutput(outputReader);
outputReader.Dispose();
double sampleRate = 0;
int channelCount = 0;
foreach (CMFormatDescription formatDescription in track.FormatDescriptions){
if (formatDescription.AudioFormats.Length != 0){
AudioFormat format = formatDescription.AudioFormats[0];
sampleRate = format.AudioStreamBasicDescription.SampleRate;
channelCount = format.AudioStreamBasicDescription.ChannelsPerFrame;
break;
}
}
int bytesPerSample = 2 * channelCount;
outputReader = (AVAssetReaderTrackOutput)reader.Outputs[0];
if (!reader.StartReading()){
return;
}
List flatBuffer = new List();
List> buffers = new List>();
string bufferString = string.Empty;
for (int i = 0; i < 16; i++){
CMSampleBuffer sampleBuffer = outputReader.CopyNextSampleBuffer();
List buffer = extractBuffer(sampleBuffer, i, bytesPerSample, channelCount);
flatBuffer.AddRange (buffer);
sampleBuffer.Dispose();
}
extractBuffer 方法看起来像这样
private List extractBuffer(CMSampleBuffer sampleBuffer, int index, int bytesPerSamples, int channelCount){
CMBlockBuffer blockBuffer = sampleBuffer.GetDataBuffer ();
int dataLength = (int)blockBuffer.DataLength;
NSMutableData data = NSMutableData.FromLength (dataLength);
blockBuffer.CopyDataBytes (0, (uint)dataLength, data.MutableBytes);
int sampleCount = sampleBuffer.NumSamples;
float[] resultBuffer = new float[sampleCount];
unsafe{
float* samples = (float*)data.MutableBytes;
for (int i = 0; i < sampleCount; i++){
float left = (float)*samples++;
float right = left;
if (channelCount == 2){
right = (float)*samples++;
}
resultBuffer [i] = (float)((left + right) / 2);
}
}
List result = new List(resultBuffer);
resultBuffer = null;
blockBuffer.Dispose ();
blockBuffer = null;
return result;
}
请注意,为了稍后的分析,我将信号重新转换为单声道信号。
现在我应该在 xamarin 和 adobe air 中获得相同的 mp3 数据,但事实并非如此。大多数时候我得到相同的值,但不是相同的索引。我想 adobe 的工程师知道他们在做什么,所以我在这里错过了什么?
谢谢你的帮助