0

Alvas オーディオ ライブラリを使用してファイルを Mp3 から Wave 形式に変換し、編集してから Mp3 に戻します。Wave への変換は正常に機能しますが、MP3 に変換しようとすると問題が発生します。何らかの理由で、この失敗は、バックグラウンド ワーカーを使用して最初の変換を実行しているという事実に関連しています。

ライブラリのソース コードがないと、何が起こっているのかを理解しようとするのが難しくなることはわかっていますが、何が問題なのかについて誰かが提案してくれることを願っています。

バックグラウンド ワーカーなしでこの同じコードを同期的に呼び出すと、完全に機能します。何か案は?

変換を実行するためにバックグラウンド ワーカーから呼び出すコードは次のとおりです。

    public Tuple<float, float> convertMp3ToWav(Track track) //with Detection, duration check, and TODO: silence removal
    {
        try
        {
            string baseFile = Path.GetFileName(track.location);
            ////////////////////////////
            //string baseFile = track.location.Remove(track.location.Length - 4);
            string outputFile = directory + "Temp\\" + baseFile.Remove(baseFile.Length - 4) + ".wav";
            cleanupFiles.Add(outputFile);
            if (!File.Exists(outputFile))
            {
                int soundStart = -1;
                int soundEnd = 0;
                Mp3Reader mr = new Mp3Reader(File.OpenRead(track.location));
                IntPtr mp3Format = mr.ReadFormat();
                IntPtr pcmFormat = AudioCompressionManager.GetCompatibleFormat(mp3Format, AudioCompressionManager.PcmFormatTag);
                AcmConverter acm = new AcmConverter(mp3Format, pcmFormat, false);

                int sec = 1024;
                int i = 0;

                bool soundFound = false;
                while (true)
                {
                    byte[] mp3Data = mr.ReadDataInBytes(i, sec);
                    if (mp3Data.Length == 0)
                    {
                        break;
                    }
                    byte[] pcmData = acm.Convert(mp3Data);
                    foreach (byte d in pcmData) //THIS SECTION CHECKS IF THE Section in question has silence
                    {
                        if (d != 0)
                        {
                            soundFound = true;
                        }

                    }
                    if ((soundStart == -1) && (soundFound == true)) //if no beginning sound has been found yet, but has now been found
                    {
                        soundStart = i; //This will be precise to whatever value of sec has been chosen
                    }
                    else if ((soundStart != -1) && (soundFound == true)) //this is a possible end value
                    {
                        soundEnd = i;   //this value will be rewritten each time there is sound found after soundstart is set.
                                        //so this value will remain the same if no further sound is found in the track, and will represent the 
                                        //end of sound in the track
                    }

                    soundFound = false;
                    i += sec;
                }
                int finalDuration = soundEnd - soundStart;
                mr.Close();
                Mp3Reader reader = new Mp3Reader(File.OpenRead(track.location));
                IntPtr thisFormat = reader.ReadFormat();
                byte[] completeTrack = reader.ReadDataInBytes(soundStart, finalDuration);
                byte[] convertedTrack = AudioCompressionManager.Convert(thisFormat, pcmFormat, completeTrack, false);
                WaveWriter ww = new WaveWriter(File.OpenWrite(outputFile), AudioCompressionManager.FormatBytes(pcmFormat));
                ww.WriteData(convertedTrack);
                ww.Close();
                reader.Close();

                float bpm = performBeatDetection(track);
                float duration = getTrackDuration(track);

                return new Tuple<float, float>(bpm, duration);
            }
            else
            {
                //File already exists, just remove silence, get bpm and duration
                //string silenceRemoved = removeSilenceFromTrack(outputFile);
                float bpm = performBeatDetection(track);
                float duration = getTrackDuration(track);
                return new Tuple<float, float>(bpm, duration);
            }
        }
        catch (Alvas.Audio.AudioException e)
        {
            MessageBox.Show("ERROR: " + e.ToString());
            return new Tuple<float, float>(0f, 0f);
        }
    }

編集:

特定の障害は、ライブラリからの例外です。Alvas を使用してファイルをあるオーディオ形式から別のオーディオ形式に変換する場合は、最初にファイルの現在の形式の形式を読み込みます。

IntPtr mp3Format = mr.ReadFormat();

次に、変換するには、静的メソッドを呼び出します

AudioCompressionManager.GetCompatibleFormat(oldFormat, newFormatTag);

バックグラウンド ワーカーを使用した後にこの最後のメソッドを呼び出すと、下手な英語で「フォーマット変換に成功しません」という例外がスローされます。ライブラリで少し異なる方法を使用します。

AudioCompressionManager.GetCompatibleFormatList(oldFormat);

バックグラウンド ワーカーを使用せず、後者のメソッド (GetCompatibleFormatList) を使用すると、51 個の結果が返されることがわかります。そのうちの 1 つは、必要な mp3 形式への変換です。

バックグラウンド ワーカーを使用して最初の変換を実行した後にこれと同じ方法を実行すると、20 個の結果しか返されず、いずれも互換性のある mp3 形式ではありません。

4

1 に答える 1

0

「トラブル」を定義しないと、特定するのは難しいです。しかし、おそらくこれらのアイデアが役立つでしょう:

  • バックグラウンド ワーカーによって使用されるデータ (またはファイル) のいずれかが、フォアグラウンド スレッドによって処理されますか? (たとえば、track使用中にパラメーターが何らかの方法で破棄または変更される可能性はありますか?)

  • バックグラウンド スレッドの実行中に、フォアグラウンド スレッドはライブラリ API を呼び出しますか? 複数のスレッドでライブラリ コードを呼び出すコードはありますか? フォアグラウンド スレッドは、バックグラウンド スレッドによって結果が完了するのを適切に待機していますか? (たとえば、フォアグラウンド スレッドをバックグラウンド スレッドに参加させて (またはビジー待機/スリープを実行して)、処理が実行されている間だけ待機するようにテストしてみてください。問題は解決しますか?)

  • ライブラリは、特定のスレッドで呼び出される必要がある可能性があることを行いますか?特に、進行状況バーなどを更新するために UI スレッドで実行する必要がありますか? (これには、UI スレッドを介して呼び出す必要がある可能性がある、コード内のイベント ハンドラーの呼び出しが含まれます)

  • メインスレッドに返す戻り値の型以外のデータはありますか? その場合、同期 (ロックや揮発性など) を使用して、正しい (最新の) 値を読み取っていますか?

  • 処理メソッドが戻る前に、すべてのデータが書き込まれ、ディスクにフラッシュされ、すべてのファイルが閉じられますか?

于 2013-03-26T23:30:03.173 に答える