1

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;
}

後で分析するために、信号をモノとして再変換することに注意してください。

これで、同じ mp3 に対して xamarin と adobe air の同じデータを取得する必要がありますが、そうではありません。ほとんどの場合、同じ値を取得しますが、同じインデックスでは取得しません。adobe のエンジニアは何をしているのかを知っていると思いますが、ここで何を見逃したのでしょうか?

ご協力いただきありがとうございます

4

0 に答える 0