Help needed to create a plugin for fixing dv clicks

Share your Audacity/Nyquist plug-ins here, or test drive the latest plug-ins submitted by Audacity users.

After testing a plug-in from this forum, please post feedback for the plug-in author.
janolap1
Posts: 8
Joined: Fri Nov 02, 2012 11:26 pm
Operating System: Please select

Help needed to create a plugin for fixing dv clicks

Post by janolap1 » Sat Nov 03, 2012 8:28 pm

Hi,

I'm really new in those forums, but I have used Audacity for years.

I have a problem with a audio track from my dv camcorder (mini-dv sd).
Here is the problem : from time to time, during the video, the sound makes a sort of "click".

When I import the sound of the video inside audacity, I found that the "clicks" are either left or right.
And I have found that the structure of the click is quite simple :
A sample every 4 or 5 (or 6 or 7) has a db value of zero.

I could fix it by raising the sample to it's (approximative) original value manually, but it's an enormous work.

So I thought about creating a plugin for Audacity. I make some programs, but in a C, or php, or basic syntax. But Nyquist has a quite different syntax ; and I would like to work with individual samples (which is not covered by the tutorial).

So I have wrotten a pseudo-code for my plugin. So if I someone could translate it into a Nyquist plugin, it would save me a lot of time (and could help my friends with having an usable video of their show...).

Here is the pseudo code :

Code: Select all

for $i=0 to numberOfSample(selection)-1
{
 if (($i>0) and ($i<numberOfSample(selection)-1)) then
 {
  if (getdbSample(selection, $i) ==0)
  {
   putdbSample(selection, $i, (getdbSample(selection, $i)+getdbSample(selection, $i))/2);
  }
 }
}
Where numberOfSample(s) is a function that returns the number of samples in the selection s;
Where getdbSample(s,n) is a function that returns the db value of the sample number n in the selection s;
Where putdbSample(s,n,v) is a function that replaces the db value of the sample number n in the selection s by the value v;

Could you help me with this ?

Cordially

Jean CARTIER

kozikowski
Forum Staff
Posts: 69384
Joined: Thu Aug 02, 2007 5:57 pm
Operating System: macOS 10.13 High Sierra

Re: Help needed to create a plugin for fixing dv clicks

Post by kozikowski » Sat Nov 03, 2012 10:54 pm

This is me watching. As with most problems like this that deal with Real World Problems, you have to determine when to apply the correction. While it's not impossible for an actual show to go to "all zero bits" for a duration, it's only unlikely. Similarly, if the samples are not zero, but actual digital damage, then the samples may not conform to the "all zeros" condition for filter application.

I'd get the camcorder fixed myself. How old is it? We have some older SD Mini-DV camcorders in the stable that routinely drop one of the video heads on occasion.

If you have one of the cameras that supports plug-in microphones, you might try plugging and unplugging several times to "clean" the contacts. It's very unlikely that once side of a digital stereo bitstream suddenly vanishes, it's much more likely something ahead of the D/A converter is frying.

Koz

Robert J. H.
Posts: 3633
Joined: Thu May 31, 2012 8:33 am
Operating System: Windows 10

Re: Help needed to create a plugin for fixing dv clicks

Post by Robert J. H. » Sun Nov 04, 2012 4:04 am

What do you mean by dB value of 0?
0 dB is full power (amplitude 1 or -1) and -inf dB is amplitude 0.
Let's talk for now in terms of amplitude (-1 to 1). I presume that one sample could be 0.707 the next (drop-out) 0 and then 0.7 again.
This can also be the case for samples under the center line (-0.6 0 -0.8), I guess.
And this happens every 4th to 7th sample? You know, that signal has already lost a huge amount of information. I doubt if the results will be satisfying.
Anyway, here is some sample code with some arbitrary sample values that have such drop outs.

Code: Select all

(setf *sr* *sound-srate*)
(setf selected-samples (snd-from-array 0 *sr* (vector
  0.0 .1 0.3 0.5 0.8 0.0 0.7 0.4 0.1 
  -0.3 -0.6 -0.7 0 -0.8 -0.4 -0.2 0.0 0.0)))
(setf correction 
  (diff 
    (snd-chase selected-samples (/ 2 *sr*) (/ 2 *sr*))     selected-samples))  
(setf result (sim (mult 3 Correction) selected-samples))
;; Let's compare the results
(setf before (snd-samples selected-samples ny:all))
(setf after (snd-samples result ny:all))
(setf corr-by (snd-samples (diff result selected-samples) ny:all))
(format t "Before corrected by after~%")
(dotimes (smp(length before))
  (format t "~a    ~a          ~a~%"
    (aref before smp)
    (aref corr-by smp)
    (aref after smp)))
Thats not yet a plug-in, its for demonstration purpose only. Copy the code to the Nyquist prompt, press the debug button and control if the correction somewhat resembles what you have in mind.
If we are on the right way with this solution, there will be no need for loop structures and reading out each sample (that's very slow and risky in Nyquist).
Snd-chase is a kind of lowpass filter, but not in the usual sense. We use it here to smooth the abrupt changes from high to low and high again within 3 samples.
(If you want to look up any function or command, you can install my plug-in:)
Nyquist/Xlisp Reference

janolap1
Posts: 8
Joined: Fri Nov 02, 2012 11:26 pm
Operating System: Please select

Re: Help needed to create a plugin for fixing dv clicks

Post by janolap1 » Sun Nov 04, 2012 10:21 am

Thank you for all those replies...

There was an error in my pseudo code :

Code: Select all

for $i=0 to numberOfSample(selection)-1
{
 if (($i>0) and ($i<numberOfSample(selection)-1)) then
 {
  if (getdbSample(selection, $i) ==0)
  {
   putdbSample(selection, $i, (getdbSample(selection, $i-1)+getdbSample(selection, $i+1))/2);
  }
 }
}
I'll try what you said and tell you if I succeed.

janolap1
Posts: 8
Joined: Fri Nov 02, 2012 11:26 pm
Operating System: Please select

Re: Help needed to create a plugin for fixing dv clicks

Post by janolap1 » Sun Nov 04, 2012 8:19 pm

Hi,

To answer Koz, my dv cam is pretty old.
But I think there's a problem with the 16bit audio recording.
Maybe a problem with the tape. I have to investigate further.

The sample code of Robert : I think, being a newbie with Nyquist langage, that you create a sound from the array and try to correct it.
There is a error when debugging (i'm using audacity 1.3.0-beta) : error: unbound function - DIFF
Ok, using Audacity 2 it runs.

Well, I think this could help, but is there a way to do this :
if sample==0 then sample= (previoussample+nextsample)/2

Let me show you 2 pictures of the samples : one before correction and one after manual correction :
Image
Image

Cordially

Jean CARTIER

steve
Site Admin
Posts: 81653
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Help needed to create a plugin for fixing dv clicks

Post by steve » Sun Nov 04, 2012 10:08 pm

janolap1 wrote: Well, I think this could help, but is there a way to do this :
if sample==0 then sample= (previoussample+nextsample)/2
Yes that could be done, but Robert is trying to (cleverly) avoid bit-wise processing as bit-wise processing in Audacity is notoriously slow.

Robert's code will work where there is a sudden large drop in the value of one sample value from the surrounding audio samples, and it will work pretty quickly. Unfortunately I don't think that it is going to work very well on your damaged audio because the drop to zero is probably not far enough.

If you want to try Robert's code, this is a short version of the "correcting" part of the code. Select a section of the damaged audio, then copy and paste this code into the Nyquist Prompt effect to run it:

Code: Select all

(defun correct (sig &aux (slew-time (/ 2 (snd-srate sig))))
  (sim
    (mult 3 (snd-chase sig slew-time slew-time))
    (mult -2 sig)))

(multichan-expand #'correct s)
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

Robert J. H.
Posts: 3633
Joined: Thu May 31, 2012 8:33 am
Operating System: Windows 10

Re: Help needed to create a plugin for fixing dv clicks

Post by Robert J. H. » Sun Nov 04, 2012 11:04 pm

(Thanks Steve)
Hi Jean
The code should also work with your old audacity version since steve has replaced (diff s1 s2) with (sim s1 (mult -1 s2)).
As you can easily test with my example above, the code works also when the drop out isn't exactly 0 (0.1 works still).
As I said before, the code is not yet on production level, so don't be surprised when it doesn't work entirely satisfactory the first time.
Especially the multiplication with the factor 3 is arbitrary and not save as such. Let me illustrate this: If the sample triple is (1.0 0.0 1.0) the calculated correction will be 0.5 x 3 = 1.5 and therefore 4 db to high. It would be wiser to take the square root (one or more times) of the calculated correction. For 0.5 we would get:
0.5 > 0.707 > 0.841 > 0.917 ...
You see, we will come pretty close to 1 the higher the fractal power is. Unfortunately, this won't work for negative values. We therefore have to separate the lower and upper parts of the wave form and recombine them in the end.
But first, let us know if the code improves the sound at least partially.

steve
Site Admin
Posts: 81653
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Help needed to create a plugin for fixing dv clicks

Post by steve » Sun Nov 04, 2012 11:07 pm

If you only need to process very short sections at a time (say, under a couple of seconds), then your algorithm can be applied quite simply.
I've added a lot of comments to this code so that hopefully you can see what it is doing.
Note that the sample values must be exactly zero to be corrected.

Code: Select all

; limit selection to 100,000 samples
(setq max-samples (min 100000 (truncate len)))

;;; Function to correct zero samples
(defun correct (sig)
  ;grab samples in an array
  (setf s-array (snd-samples sig max-samples))
  ;; main loop
  (do ((count 1 (1+ count)))
      ; loop through samples
      ((>= count (- max-samples 2))
        ; return sound from samples
        (snd-from-array 0 *sound-srate* s-array))
    ; when sample value is zero
    (when (= (aref s-array count) 0)
      ;; set new 'average' value
      (setf (aref s-array count)
        (/ (+ (aref s-array (1- count))
           (aref s-array (1+ count)))
          2.0))
      ; and skip the next 3 samples
      (setq count (+ 3 count)))))

;; check selection length and if OK run the program
(if (<= len max-samples)
  ; run it
  (multichan-expand #'correct s)
  ; print an error message
  (format nil "Error.~%maximum selection length is ~a seconds."
    (/ max-samples *sound-srate*)))
Again you can run this code in the Nyquist Prompt effect.
Don't try to use this simple approach on selections more than a few seconds or you will probably crash Audacity.
This version is limited to 100,000 samples which should be safe.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

steve
Site Admin
Posts: 81653
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: Help needed to create a plugin for fixing dv clicks

Post by steve » Sun Nov 04, 2012 11:16 pm

Just a little note that I didn't comment:
The plug-in assumes that is a zero sample is found, the next three samples are not faulty, so it skips them by adding 3 to the counter. That's just to make it run a little quicker since you said that the zero samples only occur every 4 or more samples.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

janolap1
Posts: 8
Joined: Fri Nov 02, 2012 11:26 pm
Operating System: Please select

Re: Help needed to create a plugin for fixing dv clicks

Post by janolap1 » Mon Nov 05, 2012 11:54 pm

Hi and thank you !

You're great.

Using robert's code, the effect expected is not reached.

I have adapted Steve code like this to make it work on my sample :

Code: Select all

    ; limit selection to 100,000 samples
    (setq max-samples (min 100000 (truncate len)))

    ;;; Function to correct zero samples
    (defun correct (sig)
      ;grab samples in an array
      (setf s-array (snd-samples sig max-samples))
      ;; main loop
      (do ((count 1 (1+ count)))
          ; loop through samples
          ((>= count (- max-samples 2))
            ; return sound from samples
            (snd-from-array 0 *sound-srate* s-array))
        ; when sample value is zero
        (when (< (abs (aref s-array count)) 0.01)
          ;; set new 'average' value
          (setf (aref s-array count)
            (/ (+ (aref s-array (1- count))
               (aref s-array (1+ count)))
              2.0))
          ; and skip the next 3 samples
          (setq count (+ 1 count)))))

    ;; check selection length and if OK run the program
    (if (<= len max-samples)
      ; run it
      (multichan-expand #'correct s)
      ; print an error message
      (format nil "Error.~%maximum selection length is ~a seconds."
        (/ max-samples *sound-srate*)))
And it works !

So now, I have to isolate every click and apply this nyquist patch !

Thanx a lot !

I have to learn Nyquist now...

Post Reply