简体   繁体   中英

I can't figure out why this code is failing when used with a background worker

I am using the Alvas Audio library to convert files from Mp3 to Wave format so that I can edit them, then convert them back to Mp3. The conversion to Wave works fine, but when I try to convert back to Mp3 I run into trouble. For some reason, this failure is linked to the fact that I use a background worker to perform the initial conversion.

I know that without having the source code of the library makes it difficult to try and figure out what's going on, but I'm hoping that someone might have a suggestion of what might be going wrong.

When I call this same code synchronously without the background worker, it works perfectly. Any Ideas?

Here's the code I call from the background worker to perform the conversion:

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

EDIT:

The specific failure is an exception from the library. When you want to convert a file from one audio format to another with Alvas, you first read in the format of the file's current format, like where you see

IntPtr mp3Format = mr.ReadFormat();

Then to convert, you call the static method

AudioCompressionManager.GetCompatibleFormat(oldFormat, newFormatTag);

When I call this last method after having used a background worker, it throws an exception in bad English "It is not succeeded to format conversion". Using a slightly different method in the library:

AudioCompressionManager.GetCompatibleFormatList(oldFormat);

reveals that when I do not use the background worker, and I use the latter method (GetCompatibleFormatList), it returns 51 results, one of which is a conversion to the mp3 format that I want.

If I perform this same method after performing the initial conversion using the background worker, it returns only 20 results, none of which is a compatible mp3 format.

It's hard to be specific when you don't define "trouble". But perhaps these ideas will help:

  • Does any of the data (or files) used by the background worker get touched by the foreground thread? (eg could the track parameter get disposed or modified in any way while it's being used?)

  • Does the foreground thread call any of the library APIs while the background thread is running? Does any of your code call into the library code on more than one thread? Does your foreground thread wait properly for the results to be completed by the background thread? (eg as a test try just making your foreground thread Join the background thread (or do a busy wait/sleep) so it simply waits while the processing is executed - do the problems go away?)

  • Does the library do anything that might require it to be called on a specific thread - In particular, might it need to be run in the UI thread to update progress bars or anything like that? (This includes calling event handlers in your code that may need to invoke across to the UI thread)

  • Is there any data other than the return type that you pass back to the main thread? If so are you using synchronisation (locks or volatile etc) to ensure you read the correct (latest) values?

  • Are you sure all data is written, flushed to disk, and all files closed before your processing methods return?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM