How to detect errors/flaws in audio files?

Started by Smoothie, 13 Aug '03 - 08:44

Smoothie

Does anyone know how to go about detecting flaws such as skips, pops, sync errors and other flaws in audio (mp3) files?

Source examples (Delphi preferred) would be perfect, but any push in the right direction would be most appreciated.

- Smoothie.

Sebastian_Mares

You will have to check each frame of the MP3 file and analyze its header. If one of the following things changes, then you have found a sync. error:
  • Channel mode (Stereo <-> Mono)
  • Sampling rate
  • MPEG version
  • MPEG layer
Bitrate changes are OK, as there are files with VBR.

I hope you know how to check for the above values. If not, drop a line and I will be glad to assist you (although I don't know Delphi very well).

Sebastian_Mares

By the way, pops and skips are usually caused by sync. errors. :)

Smoothie

Sebastian,

thank you! I have however tried a lot of apps that scans for sync errors, and since there necessarily doesn't have to be synch errors (I'm thinking about CD read errors during ripping), I am very interested in being able to detect errors that occours during/before encoding. From what I can understand, I would have to use BASS_ChannelGetData and analyze the raw data for patterns matching such errors ... any suggestions?

That being said, I also like to scan for sync errors - to include such a check too. If you have any code samples to read all the frame headers and extract the header data, I would very much appreciate that (any code provided here, will be used in a freeware app made available for the public, if I succeed :)

- Smoothie.

Sebastian_Mares

If you use MusicMatch Jukebox or any other encoder which creates the MP3 on-the-fly, whenever you hear a pop, crack or skip (because the CD-ROM drive was not able to position the laser correctly), a sync. error has occurred (99,99% of the time).
If you use an encoder which creates WAVs first and then uses an external MP3 encoder, then you will have to analyze the sound "by-hand".

Smoothie

Sebastian,

do you have a code snippet for extracting the appropriate frame header data you could share? Any language is fine by me.

- Smoothie.

(lol 10==2)

bigjim

I think you will need some algorithms or a way of detecting a very sharp rise in the level of a file compared to the rest of the audio.

Ive always noticed that crackles and pops mainly are well above the normal audio level of a song ;D

That should most identify pops and crackles.

Sebastian_Mares


QuoteSebastian,

do you have a code snippet for extracting the appropriate frame header data you could share? Any language is fine by me.

- Smoothie.

(lol 10==2)

Sorry to tell, but I am very busy at the moment, as I have to reinstall both systems of mine (Windows XP and Windows 2000). I am currently configuring my servers and didn't get to install Visual Basic yet. The only code I have got is really huge, not commented and contains stuff which surely won't be interesting and confusing for you (I was working on an MP3 analyzer).
Anyway, do you want to scan MP3 files only, or MP1 and MP2, too. Also, are the MP3 files MPEG 1 (44.1 KHz) or do you plan to scan MPEG 2 and MPEG 2.5, too? I need this information because each format has another frame size.

Smoothie

bigjim,
thanks for your input, I was thinking along the same lines myself. Scanning some files with CD read errors successfully (or so it seems) detects the correct error position/offset with the code below. From what I can understand, this will read the mpeg data into the buffer where I can access the channel's audio level by buf
  • . Is this the correct way of doing it?

Sebastian,
mp3 files only.

- Smoothie.

---

procedure TMainForm.ScanFile(FileName: String);
var Buf: array[1..10000] of shortint;
    Count, Chan, Pos, CurPos, a, b, i, ZBytes, ZOffset: Longint;
    ListItem: TListItem;
begin
  Chan := BASS_StreamCreateFile(False, PChar(FileName), 0, 0, BASS_STREAM_DECODE);
  Pos := BASS_StreamGetLength(Chan);
  a := 0;
  ZBytes := 0;
  ZOffset := 0;
  StatusPane.Caption := 'Reading mp3 data...';

  while (BASS_ChannelIsActive(Chan) > 0) do begin
    b := BASS_ChannelGetData(Chan, @Buf, 10000);
    Application.ProcessMessages;

    for i := 1 to 10000 do begin
      if Buf[i] = 0 then begin
        inc(ZBytes);
        if ZOffset = 0 then ZOffset := BASS_ChannelGetPosition(Chan) + i;
      end else begin
        if ZBytes > 10 then begin
          ListItem := List.Items.Add;
          ListItem.Caption := IntToStr(ZOffset);
          ListItem.SubItems.Add(IntToStr(ZBytes));
          CurPos := BASS_ChannelGetPosition(Chan)+i;
          ListItem.SubItems.Add(FloatToStr(BASS_ChannelBytes2Seconds(Chan, CurPos)));
          ListItem.SubItems.Add('Silence detected');
          ZBytes := 0;
          ZOffset := 0;
        end else begin
          ZBytes := 0;
          ZOffset := 0;
        end;
      end;
    end;
end;

bigjim

QuoteFrom what I can understand, this will read the mpeg data into the buffer where I can access the channel's audio level by buf
  • . Is this the correct way of doing it?
Yep your correct thats how you access the data :evil: