c# - 我无法弄清楚为什么这个代码在与后台工作人员一起使用时会失败

标签 c# audio backgroundworker

我正在使用 Alvas Audio 库将文件从 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);

揭示当我不使用后台 worker ,而我使用后一种方法(GetCompatibleFormatList)时,它会返回 51 个结果,其中一个是转换为我想要的 mp3 格式。

如果我在使用后台工作程序执行初始转换后执行相同的方法,它只返回 20 个结果,其中没有一个是兼容的 mp3 格式。

最佳答案

当您不定义“麻烦”时,很难具体。但也许这些想法会有所帮助:

  • 后台工作人员使用的任何数据(或文件)是否被前台线程触及? (例如,track 参数在使用时是否可以以任何方式处置或修改?)
  • 后台线程运行时,前台线程是否调用任何库 API?您的任何代码是否在多个线程上调用库代码?您的前台线程是否正确等待后台线程完成结果? (例如,作为一个测试,尝试让你的前台线程加入后台线程(或做一个忙碌的等待/ sleep ),所以它只是在执行处理时等待 - 问题会消失吗?)
  • 该库是否做了任何可能需要在特定线程上调用它的事情 - 特别是,它是否需要在 UI 线程中运行以更新进度条或类似的东西? (这包括在您的代码中调用可能需要跨到 UI 线程调用的事件处理程序)
  • 除了传回主线程的返回类型之外,还有其他数据吗?如果是这样,您是否使用同步(锁或 volatile 等)来确保您读取正确的(最新)值?
  • 您确定在处理方法返回之前所有数据都已写入、刷新到磁盘并且所有文件都已关闭吗?
  • 关于c# - 我无法弄清楚为什么这个代码在与后台工作人员一起使用时会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15648495/

    相关文章:

    c# - 在 WPF 中是否有使用后台 worker 的替代方法?

    asp.net-core - .NET CORE Lifetime 和 DI 注入(inject)的后台任务

    c# - WPF中BackgroundWorker线程如何直接访问UI线程?

    c# - 将 IQueryable 与 IEnumerable 连接成 IQueryable

    c# - 如何从 XmlReader 构建 XmlNode

    c# - 为什么我不能用 List<Tuple<string, bool>> 实例化 List<Object>?

    java - Android AudioFocus onAudioFocusChange 不监听更改

    c# - 如何在 C# 项目中使用 F# 定义的类型

    audio - 如何无损连接 ogg vorbis 文件?

    python - 在 PsychoPy 中播放声音时出错 : Could not convert string to float