[cl-wav-synth-devel] newbie question

Philippe Brochard hocwp at free.fr
Mon Oct 9 19:18:44 UTC 2006


Lui Fungsin writes:

> Hi,
>
Hi, thanks a lot for your interest in cl-wav-synth!

> I just finished watching cl-wav-synth demo tutorial, it's way cool!
>
thanks :)

> I see that this is a new project and not much traffic here, so I hope
> that you guys wouldn't mind a dumb question.
>
> I'm clueless with audio and wav file format, etc.
> However, there's a simple task that I want to try my hands on with the
> cl-wav-synth library.
>
> Here're two sound files for some chinese words. Some word has more
> than one pronounciation (like the first file below) while most of the
> others only have one.
>
> http://209.172.124.170/pub/two_tone.wav
> http://209.172.124.170/pub/single_tone.wav
>
> Is it possible to programmically detect if there's a voice uttered at
> the beginning of a wav file, then some short period of silence, and
> then another voice uttered.
>
> If this is the case, I want to split that into two files (break at the
> silence). Otherwise I can just leave it alone.
>
> If this can be done I'd greatly appreciate if someone can briefly
> describe the procedure, or can point me to a right direction (url to
> read, etc).
>
Here is how I write this (load it from slime or the clim repl):

--------------------------------------------------
(in-package :wav)

(defun find-peak (sample &optional (max-level 5000) (min-level 100) (min-index 1000))
  "Find the number of peak in a sample. Return the tone count and
  there index in a list as two values"
  (with-slots (data) sample
    (let ((count 0)
	  (find-max nil)
	  (find-min 0)
	  (acc nil))
      (loop for sample across data
	    for index from 0 do
	    (cond ((> (abs sample) max-level) (setf find-max t
						    find-min 0))
		  ((< (abs sample) min-level)
		   (incf find-min)
		   (when (and find-max (> find-min min-index))
		     (incf count)
		     (setf find-max nil)
		     (push index acc)))
		  (t (setf find-min 0))))
      (values count (nreverse acc)))))
--------------------------------------------------


Then in the clim REPL:

WAV> Load As Sample (pathname) single_tone.wav
WAV> (with-sample (find-peak it))
0 1
1 (17525)

WAV> Load As Sample (pathname) two_tone.wav
WAV> (with-sample (find-peak it))
0 2
1 (23303 60504)

WAV> (set-sample (mix it (delay it 4)))
WAV> (with-sample (find-peak it))
0 4
1 (23303 60504 111503 148704)


The first value is the number of tone in the file.
The second value is a list of each tone index.

Then you can do what you want with this value.

For example to isolate the first tone:

WAV> (set-sample (cut-i it 0 23303))
WAV> (with-sample (write-sample "first-tone.wav" it))


To isolate the second tone:

WAV> (set-sample (cut-i it 23303 60504))

Etc...

And if you want to automate this and save a file per tone:

--------------------------------------------------
(with-sample
  (multiple-value-bind (total-count index)
      (find-peak it)
    (loop for i in index
	  for s = 0 then e
	  for e = i
	  for count from 0
	  do (write-sample (format nil "tone-~A.wav" count)
			   (cut-i it s e)))))
--------------------------------------------------


Note: a sample is just a wav header (bit per sample...) and a big
array of data.

You can adjust levels:
  - Max and min level are detection levels.
  - Min index is the minimal length of the silence in sample index.


> Many thanks.
>
I hope that helps.

> fungsin
>
Philippe

-- 
Philippe Brochard    <hocwp at free.fr>
                      http://hocwp.free.fr

-=-= http://www.gnu.org/home.fr.html =-=-



More information about the Cl-wav-synth-devel mailing list