changeset 32:ea905bc19458

update doc
author Amine Sehili <amine.sehili@gmail.com>
date Tue, 01 Dec 2015 20:13:02 +0100
parents 77f218f8b9d7
children d28d94bf6b39
files auditok/cmdline.py auditok/core.py auditok/dataset.py auditok/io.py auditok/util.py demos/audio_tokenize_demo.py doc/apitutorial.rst doc/cmdline.rst doc/conf.py doc/figures/figure_1.png doc/figures/figure_2.png doc/index.rst doc/util.rst setup.py
diffstat 14 files changed, 1455 insertions(+), 298 deletions(-) [+]
line wrap: on
line diff
--- a/auditok/cmdline.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/auditok/cmdline.py	Tue Dec 01 20:13:02 2015 +0100
@@ -236,7 +236,7 @@
     
     line = plt.axhline(y=energy_as_amp, lw=1, ls="--", c="r", label="Energy threshold as normalized amplitude")
     plt.plot(t, signal)
-    legend = plt.legend(["Detection threshlod"], bbox_to_anchor=(0., 1.02, 1., .102), loc=1, fontsize=16)
+    legend = plt.legend(["Detection threshold"], bbox_to_anchor=(0., 1.02, 1., .102), loc=1, fontsize=16)
     ax = plt.gca().add_artist(legend)
 
     plt.xlabel("Time (s)", fontsize=24)
--- a/auditok/core.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/auditok/core.py	Tue Dec 01 20:13:02 2015 +0100
@@ -1,9 +1,3 @@
-'''
-September 2015
-@author: Amine SEHILI <amine.sehili@gmail.com>
-
-'''
-
 from auditok.util import DataValidator
 
 
@@ -12,28 +6,12 @@
 
 
 class StreamTokenizer():
+    """
+    Class for stream tokenizers. It implements a 4-state automaton scheme
+    to extract sub-sequences of interest on the fly.
     
+    :Parameters:
     
-    SILENCE = 0
-    POSSIBLE_SILENCE = 1
-    POSSIBLE_NOISE = 2 
-    NOISE = 3
-    
-    STRICT_MIN_LENGTH = 2
-    DROP_TRAILING_SILENCE = 4
-    # alias
-    DROP_TAILING_SILENCE = 4
-    
-    def __init__(self, validator, 
-                 min_length, max_length, max_continuous_silence,
-                 init_min=0, init_max_silence=0,
-                 mode=0):
-        """
-        Class for stream tokenizers. It implements a 4-state automaton scheme
-        for interesting sub-sequences extraction.
-        
-        **Parameters:**
-        
         `validator` :
             instance of `DataValidator` that implements `is_valid` method.
         
@@ -66,108 +44,132 @@
             
         `mode` : *(int, default=0)*
             `mode` can be:
+        
+        #. `StreamTokenizer.STRICT_MIN_LENGTH`: 
+        if token *i* is delivered because `max_length`
+        is reached, and token *i+1* is immediately adjacent to
+        token *i* (i.e. token *i* ends at frame *k* and token *i+1* starts
+        at frame *k+1*) then accept token *i+1* only of it has a size of at
+        least `min_length`. The default behavior is to accept token *i+1*
+        event if it is shorter than `min_length` (given that the above conditions
+        are fulfilled of course).
+           
+        :Examples:
+               
+        In the following code, without `STRICT_MIN_LENGTH`, the 'BB' token is
+        accepted although it is shorter than `min_length` (3), because it immediately
+        follows the latest delivered token:
             
-           1. `StreamTokenizer.STRICT_MIN_LENGTH`: 
-               if token *i* is delivered because `max_length`
-               is reached, and token *i+1* is immediately adjacent to
-               token *i* (i.e. token *i* ends at frame *k* and token *i+1* starts
-               at frame *k+1*) then accept token *i+1* only of it has a size of at
-               least `min_length`. The default behavior is to accept token *i+1*
-               event if it is shorter than `min_length` (given that the above conditions
-               are fulfilled of course).
-               
-               **Example:**
-               
-               In the following code, without `STRICT_MIN_LENGTH`, the 'BB' token is
-               accepted although it is shorter than `min_length` (3), because it immediately
-               follows the latest delivered token:
-               
+        .. code:: python
+        
+            from auditok import StreamTokenizer, StringDataSource, DataValidator
+    
+            class UpperCaseChecker(DataValidator):
+                def is_valid(self, frame):
+                    return frame.isupper()
+                   
+    
+            dsource = StringDataSource("aaaAAAABBbbb")
+            tokenizer = StreamTokenizer(validator=UpperCaseChecker(),
+                                        min_length=3,
+                                        max_length=4,
+                                        max_continuous_silence=0)
+         
+            tokenizer.tokenize(dsource)
+                    
+                    
+        :output:
+    
+         .. code:: python
+         
+            [(['A', 'A', 'A', 'A'], 3, 6), (['B', 'B'], 7, 8)]
+
+
+        The following tokenizer will however reject the 'BB' token:
+     
+        .. code:: python
+                
+            dsource = StringDataSource("aaaAAAABBbbb")
+            tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
+                                        min_length=3, max_length=4,
+                                        max_continuous_silence=0,
+                                        mode=StreamTokenizer.STRICT_MIN_LENGTH)
+            tokenizer.tokenize(dsource)
+        
+        :output:
             
-                    from auditok import StreamTokenizer, StringDataSource, DataValidator
+        .. code:: python
+            
+            [(['A', 'A', 'A', 'A'], 3, 6)]
+            
+           
+        #. `StreamTokenizer.DROP_TRAILING_SILENCE`: drop all tailing non-valid frames
+        from a token to be delivered if and only if it is not **truncated**.
+        This can be a bit tricky. A token is actually delivered if:
+           
+        - a. `max_continuous_silence` is reached
+           
+        :or:
+           
+        - b. Its length reaches `max_length`. This is called a **truncated** token
+           
+        In the current implementation, a `StreamTokenizer`'s decision is only based on already seen
+        data and on incoming data. Thus, if a token is truncated at a non-valid but tolerated
+        frame (`max_length` is reached but `max_continuous_silence` not yet) any tailing
+        silence will be kept because it can potentially be part of valid token (if `max_length`
+        was bigger). But if `max_continuous_silence` is reached before `max_length`, the delivered
+        token will not be considered as truncated but a result of *normal* end of detection
+        (i.e. no more valid data). In that case the tailing silence can be removed if you use
+        the `StreamTokenizer.DROP_TRAILING_SILENCE` mode.
+    
+        :Example:
+    
+        .. code:: python
+                       
+             tokenizer = StreamTokenizer(validator=UpperCaseChecker(), min_length=3,
+                                         max_length=6, max_continuous_silence=3,
+                                         mode=StreamTokenizer.DROP_TRAILING_SILENCE)
+            
+             dsource = StringDataSource("aaaAAAaaaBBbbbb")
+             tokenizer.tokenize(dsource)
         
-                    class UpperCaseChecker(DataValidator):
-                    def is_valid(self, frame):
-                        return frame.isupper()
+        :output:
+            
+        .. code:: python
+                
+            [(['A', 'A', 'A', 'a', 'a', 'a'], 3, 8), (['B', 'B'], 9, 10)]
+                    
+        The first token is delivered with its tailing silence because it is truncated
+        while the second one has its tailing frames removed.
+                    
+        Without `StreamTokenizer.DROP_TRAILING_SILENCE` the output would be:
+                        
+        .. code:: python
+         
+            [(['A', 'A', 'A', 'a', 'a', 'a'], 3, 8), (['B', 'B', 'b', 'b', 'b'], 9, 13)]
+    
         
-                    dsource = StringDataSource("aaaAAAABBbbb")
-                    tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
-                                min_length=3, max_length=4, max_continuous_silence=0)
-                 
-                    tokenizer.tokenize(dsource)
-                    
-                    
-               output:
-
-
-                #!python
-                [(['A', 'A', 'A', 'A'], 3, 6), (['B', 'B'], 7, 8)]
-
-
-               The following tokenizer will however reject the 'BB' token:
-             
-                #!python  
-                dsource = StringDataSource("aaaAAAABBbbb")
-                tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
-                            min_length=3, max_length=4, max_continuous_silence=0,
-                            mode=StreamTokenizer.STRICT_MIN_LENGTH)
-                tokenizer.tokenize(dsource)
-            
-               output:
-            
-                #!python
-                [(['A', 'A', 'A', 'A'], 3, 6)]
-                
-               
-           2. `StreamTokenizer.DROP_TAILING_SILENCE`: drop all tailing non-valid frames
-               from a token to be delivered if and only if it is not **truncated**.
-               This can be a bit tricky. A token is actually delivered if:
-               
-               - a. `max_continuous_silence` is reached
-               
-               OR
-               
-               - b. Its length reaches `max_length`. This is called a **truncated** token
-               
-               In the current implementation, a `StreamTokenizer`'s decision is only based on seen
-               data and on incoming data. Thus, if a token is truncated at a non-valid but tolerated
-               frame (`max_length` is reached but `max_continuous_silence` not yet) any tailing
-               silence will be kept because it can potentially be part of valid token (if `max_length`
-               was bigger). But if `max_continuous_silence` is reached before `max_length`, the delivered
-               token will not be considered as truncated but a result of *normal* end of detection
-               (i.e. no more valid data). In that case the tailing silence can be removed if you use
-               the `StreamTokenizer.DROP_TAILING_SILENCE` mode.
-               
-               Take the following example:
-            
-                #!python                
-                tokenizer = StreamTokenizer(validator=UpperCaseChecker(), min_length=3,
-                max_length=6, max_continuous_silence=3,
-                mode=StreamTokenizer.DROP_TAILING_SILENCE)
-                
-                dsource = StringDataSource("aaaAAAaaaBBbbbb")
-                tokenizer.tokenize(dsource)
-                
-               output:
-            
-                #!python
-                [(['A', 'A', 'A', 'a', 'a', 'a'], 3, 8), (['B', 'B'], 9, 10)]
-                
-               The first token is delivered with its tailing silence because it is truncated
-               while the second one has its tailing frames removed.
-                
-               Without `StreamTokenizer.DROP_TAILING_SILENCE` the output would be:
-                    
-                #!python    
-                [(['A', 'A', 'A', 'a', 'a', 'a'], 3, 8), (['B', 'B', 'b', 'b', 'b'], 9, 13)]
         
-            
-            
-           3. `StreamTokenizer.STRICT_MIN_LENGTH | StreamTokenizer.DROP_TAILING_SILENCE`:
-               use both options. That means: first remove tailing silence, then ckeck if the
-               token still has at least a length of `min_length`.
-        """
-        
-        
+        3. `StreamTokenizer.STRICT_MIN_LENGTH | StreamTokenizer.DROP_TRAILING_SILENCE`:
+        use both options. That means: first remove tailing silence, then ckeck if the
+        token still has at least a length of `min_length`.
+    """
+    
+    
+    SILENCE = 0
+    POSSIBLE_SILENCE = 1
+    POSSIBLE_NOISE = 2 
+    NOISE = 3
+    
+    STRICT_MIN_LENGTH = 2
+    DROP_TRAILING_SILENCE = 4
+    # alias
+    DROP_TAILING_SILENCE = 4
+    
+    def __init__(self, validator, 
+                 min_length, max_length, max_continuous_silence,
+                 init_min=0, init_max_silence=0,
+                 mode=0):
         
         if not isinstance(validator, DataValidator):
             raise TypeError("'validator' must be an instance of 'DataValidator'")
@@ -197,7 +199,7 @@
         self._mode = None
         self.set_mode(mode)
         self._strict_min_length = (mode & self.STRICT_MIN_LENGTH) != 0
-        self._drop_tailing_silence  = (mode & self.DROP_TAILING_SILENCE) != 0
+        self._drop_tailing_silence  = (mode & self.DROP_TRAILING_SILENCE) != 0
         
         self._deliver = None
         self._tokens = None
@@ -212,31 +214,31 @@
     
     def set_mode(self, mode):
         """
-        **Parameters:**
+        :Parameters:
         
-        `mode` : *(int)*
-            New mode, must be one of:
+            `mode` : *(int)*
+                New mode, must be one of:
+                    
                 
+            - a. `StreamTokenizer.STRICT_MIN_LENGTH`
             
-        - a. `StreamTokenizer.STRICT_MIN_LENGTH`
-        
-        - b. `StreamTokenizer.DROP_TAILING_SILENCE`
-        
-        - c. `StreamTokenizer.STRICT_MIN_LENGTH | StreamTokenizer.DROP_TAILING_SILENCE`
-               
-        - d. `0`
+            - b. `StreamTokenizer.DROP_TRAILING_SILENCE`
+            
+            - c. `StreamTokenizer.STRICT_MIN_LENGTH | StreamTokenizer.DROP_TRAILING_SILENCE`
                    
+            - d. `0`
+                       
         See `StreamTokenizer.__init__` for more information about the mode.
         """
         
-        if not mode in [self.STRICT_MIN_LENGTH, self.DROP_TAILING_SILENCE,
-           self.STRICT_MIN_LENGTH | self.DROP_TAILING_SILENCE, 0]:
+        if not mode in [self.STRICT_MIN_LENGTH, self.DROP_TRAILING_SILENCE,
+           self.STRICT_MIN_LENGTH | self.DROP_TRAILING_SILENCE, 0]:
             
             raise ValueError("Wrong value for mode")
         
         self._mode = mode
         self._strict_min_length = (mode & self.STRICT_MIN_LENGTH) != 0
-        self._drop_tailing_silence  = (mode & self.DROP_TAILING_SILENCE) != 0
+        self._drop_tailing_silence  = (mode & self.DROP_TRAILING_SILENCE) != 0
         
     
     def get_mode(self):
@@ -244,9 +246,10 @@
         Return the current mode. To check whether a specific mode is activated use
         the bitwise 'and' operator `&`. Example:
            
-            #!python
+        .. code:: python 
+                
             if mode & self.STRICT_MIN_LENGTH != 0:
-                ...
+               do_something()
         """
         return self._mode
         
@@ -264,28 +267,26 @@
         Read data from `data_source`, one frame a time, and process the read frames in
         order to detect sequences of frames that make up valid tokens.
         
-        **Parameters:**
+        :Parameters:
+           `data_source` : instance of the `DataSource` class that implements a 'read' method.
+               'read' should return a slice of signal, i.e. frame (of whatever \
+               type as long as it can be processed by validator) and None if \
+               there is no more signal.
         
+           `callback` : an optional 3-argument function.
+               If a `callback` function is given, it will be called each time a valid token
+               is found.
+           
+           
+        :Returns:
+           A list of tokens if `callback` is None. Each token is tuple with the following elements:
         
-        `data_source` : instance of the `DataSource` class that implements a 'read' method.
-            'read' should return a slice of signal, i.e. frame (of whatever \
-            type as long as it can be processed by validator) and None if \
-            there is no more signal.
-        
-        `callback` : an optional 3-argument function.
-            If a `callback` function is given, it will be called each time a valid token
-            is found.
-           
-           
-        **Returns:**
-        
-        A list of tokens if `callback` is None. Each token is tuple with the following elements:
-        
-            #!python
-            (data, start, end)
+            .. code python
             
-        where `data` is a list of read frames, `start`: index of the first frame in the
-        original data and `end` : index of the last frame. 
+                (data, start, end)
+            
+           where `data` is a list of read frames, `start`: index of the first frame in the
+           original data and `end` : index of the last frame. 
         
         """
         
--- a/auditok/dataset.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/auditok/dataset.py	Tue Dec 01 20:13:02 2015 +0100
@@ -1,8 +1,10 @@
 """
-This module contains links to audio files you can use for test purposes.
+.. py:module:: dataset
+   :synopsis: This module contains links to audio files you can use for test purposes.
+
+.. moduleauthor:: Amine SEHILI <amine.sehili@gmail.com>
 
 September 2015
-@author: Amine SEHILI <amine.sehili@gmail.com>
 """
 
 import os
@@ -19,4 +21,4 @@
 was_der_mensch_saet_mono_44100_lead_trail_silence = "{cd}{sep}data{sep}was_\
 der_mensch_saet_das_wird_er_vielfach_ernten_44100Hz_mono_lead_trail_\
 silence.wav".format(cd=_current_dir, sep=os.path.sep)
-""" A wave file that contains a sentence between long leading and tailing periods of silence"""
\ No newline at end of file
+""" A wave file that contains a sentence between long leading and trailing periods of silence"""
\ No newline at end of file
--- a/auditok/io.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/auditok/io.py	Tue Dec 01 20:13:02 2015 +0100
@@ -1,8 +1,27 @@
 """
 Module for low-level audio input-output operations. 
 
-September 2015
-@author: Amine SEHILI <amine.sehili@gmail.com>
+Class summary
+=============
+
+.. autosummary::
+
+        AudioSource
+        Rewindable
+        BufferAudioSource
+        WaveAudioSource
+        PyAudioSource
+        StdinAudioSource
+        PyAudioPlayer
+        
+
+Function summary
+================
+
+.. autosummary::
+
+        from_file
+        player_for
 """
 
 from abc import ABCMeta, abstractmethod
@@ -18,38 +37,32 @@
 
 
 class AudioSource():
-    __metaclass__ = ABCMeta
-    
     """ 
-    Base class for audio source.
+    Base class for audio source objects.
         
     Subclasses should implement methods to open/close and audio stream 
     and read the desired amount of audio samples.
-         
+    
+    :Parameters:
+        
+        `sampling_rate` : int
+            Number of samples per second of audio stream. Default = 16000.
+        
+        `sample_width` : int
+            Size in bytes of one audio sample. Possible values : 1, 2, 4.
+            Default = 2.
+            
+        `channels` : int
+            Number of channels of audio stream. The current version supports
+            only mono audio streams (i.e. one channel).
     """
+    
+    __metaclass__ = ABCMeta
 
     def __init__(self, sampling_rate = DEFAULT_SAMPLE_RATE,
                  sample_width = DEFAULT_SAMPLE_WIDTH,
                  channels = DEFAULT_NB_CHANNELS):
-        
-        """
-        
-        **Parameters:**
-        
-        
-        `sampling_rate` *(int)* :
-            Number of samples per second of audio stream. Default = 16000.
-        
-        `sample_width` *(int)* :
-            Size in bytes of one audio sample. Possible values : 1, 2, 4.
-            Default = 2.
-            
-        `channels` *(int)* :
-            Number of channels of audio stream. The current version supports
-            only mono audio streams (i.e. one channel).
-        
-        """
-        
+  
         if not sample_width in (1, 2, 4):
             raise ValueError("Sample width must be one of: 1, 2 or 4 (bytes)")
         
@@ -77,18 +90,18 @@
         """
         Read and return `size` audio samples at most.
         
-        **Parameters:**
+        :Parameters:
         
-        `size` : *(int)* :
-            the number of samples to read.
-        
-        **Returns:**
-        
-        Audio data as a string of length 'N' * 'smaple_width' * 'channels', where 'N' is:
-        
-        `size` if `size` < 'left_samples'
-        
-        'left_samples' if `size` > 'left_samples' 
+            `size` : int
+                the number of samples to read.
+            
+        :Returns:
+            
+            Audio data as a string of length 'N' * 'smaple_width' * 'channels', where 'N' is:
+            
+            - `size` if `size` < 'left_samples'
+            
+            - 'left_samples' if `size` > 'left_samples' 
         
         """ 
     
@@ -107,15 +120,14 @@
 
 
 class Rewindable():
-    __metaclass__ = ABCMeta
-    
     """
     Base class for rewindable audio streams.
     Subclasses should implement methods to return to the beginning of an
     audio stream as well as method to move to an absolute audio position
     expressed in time or in number of samples. 
+    """
     
-    """
+    __metaclass__ = ABCMeta
     
     @abstractmethod
     def rewind(self):
@@ -134,30 +146,29 @@
     def set_position(self, position):
         """ Move to an absolute position 
         
-        **Parameters:**
+        :Parameters:
         
-        `position` : *(int)*
-            number of samples to skip from the start of the stream
+            `position` : int
+                number of samples to skip from the start of the stream
         """
     
     @abstractmethod
     def set_time_position(self, time_position):
         """ Move to an absolute position expressed in seconds
         
-        **Parameters:**
+        :Parameters:
         
-        `time_position` : *(float)*
-            seconds to skip from the start of the stream
+            `time_position` : float
+                seconds to skip from the start of the stream
         """
         pass
     
     
 
 class BufferAudioSource(AudioSource, Rewindable):
-    
     """
-    A class that represent audio data as a memory buffer. It implements
-    methods from `io.Rewindable` and is therefore a navigable `io.AudioSource`.
+    An :class:`AudioSource` that encapsulates and reads data from a memory buffer.
+    It implements methods from :class:`Rewindable` and is therefore a navigable :class:`AudioSource`.
     """
     
     def __init__(self, data_buffer,
@@ -210,10 +221,10 @@
     def set_data(self, data_buffer):
         """ Set new data for this audio stream. 
         
-        **Parameters:**
+        :Parameters:
         
-        `data_buffer` :
-           a string buffer with a length multiple of (sample_width * channels)
+            `data_buffer` : str, basestring, Bytes
+                a string buffer with a length multiple of (sample_width * channels)
         """
         if len(data_buffer) % (self.sample_width * self.channels) !=0:
             raise ValueError("length of data_buffer must be a multiple of (sample_width * channels)")
@@ -224,11 +235,10 @@
     def append_data(self, data_buffer):
         """ Append data to this audio stream
         
-        **Parameters:**
+        :Parameters:
         
-        `data_buffer` :
-           a string buffer with a length multiple of (sample_width * channels)
-        
+            `data_buffer` : str, basestring, Bytes
+                a buffer with a length multiple of (sample_width * channels)
         """
         
         if len(data_buffer) % (self.sample_width * self.channels) !=0:
@@ -270,19 +280,17 @@
         
 
 class WaveAudioSource(AudioSource):
+    """
+    A class for an `AudioSource` that reads data from a wave file.
     
-    """ A class for an `AudioSource` that reads data from a wave file. """
+    :Parameters:
+        
+        `filename` :
+            path to a valid wave file
+    """
     
     def __init__(self, filename):
         
-        """
-        **Parameters:**
-        
-        `filename` :
-            path to a valid wave file
-        
-        """
-                
         self._filename = filename
         self._audio_stream = None
         
@@ -319,8 +327,9 @@
 
 
 class PyAudioSource(AudioSource):
-    
-    """ A class for an `AudioSource` that reads data the built-in microphone. """
+    """
+    A class for an `AudioSource` that reads data the built-in microphone using PyAudio. 
+    """
     
     def __init__(self, sampling_rate = DEFAULT_SAMPLE_RATE,
                  sample_width = DEFAULT_SAMPLE_WIDTH,
@@ -371,8 +380,9 @@
     
 
 class StdinAudioSource(AudioSource):
-    
-    """ A class for an `AudioSource` that reads data from standard input. """
+    """
+    A class for an :class:`AudioSource` that reads data from standard input.
+    """
     
     def __init__(self, sampling_rate = DEFAULT_SAMPLE_RATE,
                  sample_width = DEFAULT_SAMPLE_WIDTH,
@@ -405,7 +415,9 @@
        
            
 class PyAudioPlayer():
-    """ A class for audio playback """
+    """
+    A class for audio playback using Pyaudio
+    """
     
     def __init__(self, sampling_rate = DEFAULT_SAMPLE_RATE,
                  sample_width = DEFAULT_SAMPLE_WIDTH,
@@ -456,14 +468,14 @@
     Create an `AudioSource` object using the audio file specified by `filename`.
     The appropriate `AudioSource` class is guessed from file's extension.
     
-    **Parameters:**
+    :Parameters:
     
-    `filename` :
-        path to an audio file
+        `filename` :
+            path to an audio file.
         
-    **Returns:**
+    :Returns:
     
-    an `AudioSource` object that reads data from the given file.
+        an `AudioSource` object that reads data from the given file.
     
     """
     
@@ -475,17 +487,17 @@
 
 def player_for(audio_source):
     """
-    Return a `PyAudioPlayer` that can play data from `audio_source`.
+    Return a :class:`PyAudioPlayer` that can play data from `audio_source`.
     
-    **Parameters:**
+    :Parameters:
     
-    `audio_source` : 
-        an `AudioSource` object.
+        `audio_source` : 
+            an `AudioSource` object.
     
-    **Returns:**
+    :Returns:
     
-    `PyAudioPlayer` that has the same sampling rate, sample width and number of channels
-    as `audio_source`.
+        `PyAudioPlayer` that has the same sampling rate, sample width and number of channels
+        as `audio_source`.
     """
     
     return PyAudioPlayer(audio_source.get_sampling_rate(),
--- a/auditok/util.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/auditok/util.py	Tue Dec 01 20:13:02 2015 +0100
@@ -1,8 +1,25 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
 """
-September 2015
-@author: Amine SEHILI <amine.sehili@gmail.com>
+Class summary
+=============
+
+.. autosummary::
+
+        DataSource
+        StringDataSource
+        ADSFactory
+        ADSFactory.AudioDataSource
+        ADSFactory.ADSDecorator
+        ADSFactory.OverlapADS
+        ADSFactory.LimiterADS
+        ADSFactory.RecorderADS
+        DataValidator
+        AudioEnergyValidator
+
 """
 
+
 from abc import ABCMeta, abstractmethod
 import math
 from array import array
@@ -30,27 +47,27 @@
     
 
 class DataSource():
+    """
+    Base class for objects passed to :func:`auditok.core.StreamTokenizer.tokenize`.
+    Subclasses should implement a :func:`DataSource.read` method.
+    """
     __metaclass__ = ABCMeta
-    """
-    Base class for objects passed to `StreamTokenizer.tokenize`.
-    Subclasses should implement a `read` method.
-    
-    """
     
     @abstractmethod
     def read(self):
-        """ Read a piece of data read from this source.
-            If no more data is available, return None.
+        """
+        Read a piece of data read from this source.
+        If no more data is available, return None.
         """
     
     
 class DataValidator():
+    """
+    Base class for a validator object used by :class:`.core.StreamTokenizer` to check
+    if read data is valid.
+    Subclasses should implement :func:`is_valid` method.
+    """
     __metaclass__ = ABCMeta
-    """
-    Base class for a validator object used by `StreamTokenizer` to check
-    if read data is valid.
-    Subclasses should implement `is_valid` method.
-    """
     
     @abstractmethod
     def is_valid(self, data):
@@ -60,25 +77,33 @@
 
 class StringDataSource(DataSource):
     """
-    A class that represent a `DataSource` as a string buffer.
-    Each call to `read` returns on character and moves one step forward.
-    If the end of the buffer is reached, `read` returns None. 
+    A class that represent a :class:`DataSource` as a string buffer.
+    Each call to :func:`DataSource.read` returns on character and moves one step forward.
+    If the end of the buffer is reached, :func:`read` returns None.
+   
+    :Parameters:
+        
+        `data` : 
+            a basestring object.
+     
     """
      
     def __init__(self, data):
-        """
-        Parameters
-        ----------
-        `data` : 
-            a basestring object.
-        """
-        
+
         self._data = None
         self._current = 0
         self.set_data(data)
         
     
     def read(self):
+        """
+        Read one character from buffer.
+        
+        :Returns:
+        
+            Current character or None if end of buffer is reached
+        """
+        
         if self._current >= len(self._data):
             return None
         self._current += 1
@@ -88,10 +113,10 @@
         """
         Set a new data buffer.
         
-        Parameters
-        ----------
-        `data` : 
-            a basestring object.
+        :Parameters:
+        
+            `data` : a basestring object 
+                New data buffer.
         """
         
         if not isinstance(data, basestring):
@@ -103,19 +128,19 @@
 
 class ADSFactory:
     """
-    Factory class that makes it easy to create an `AudioDataSource` object that implements
-    `DataSource` and can therefore be passed to `StreamTokenizer.tokenize`.
+    Factory class that makes it easy to create an :class:`ADSFactory.AudioDataSource` object that implements
+    :class:`DataSource` and can therefore be passed to :func:`auditok.core.StreamTokenizer.tokenize`.
     
     Whether you read audio data from a file, the microphone or a memory buffer, this factory
-    instantiates and returns the right `AudioDataSource` object.
+    instantiates and returns the right :class:`ADSFactory.AudioDataSource` object.
     
-    There are many other features you want your `AudioDataSource` object to have, such as: 
+    There are many other features you want your :class:`ADSFactory.AudioDataSource` object to have, such as: 
     memorize all read audio data so that you can rewind and reuse it (especially useful when 
     reading data from the microphone), read a fixed amount of data (also useful when reading 
     from the microphone), read overlapping audio frames (often needed when dosing a spectral
     analysis of data).
     
-    `ADSFactory.ads` automatically creates and return object with the desired behavior according
+    :func:`ADSFactory.ads` automatically creates and return object with the desired behavior according
     to the supplied keyword arguments. 
      
     """
@@ -210,15 +235,14 @@
     def ads(**kwargs):
         
         """
-        Create an return an `AudioDataSource`. The type and behavior of the object is the result
+        Create an return an :class:`ADSFactory.AudioDataSource`. The type and behavior of the object is the result
         of the supplied parameters.
         
-        Parameters
-        ----------
+        :Parameters:
         
         *No parameters* :  
            read audio data from the available built-in microphone with the default parameters.
-           The returned `AudioDataSource` encapsulate an `io.PyAudioSource` object and hence 
+           The returned :class:`ADSFactory.AudioDataSource` encapsulate an :class:`io.PyAudioSource` object and hence 
            it accepts the next four parameters are passed to use instead of their default values.
         
         `sampling_rate`, `sr` : *(int)*
@@ -256,21 +280,21 @@
         
         `block_dur`, `bd` : *(float)*
             processing block duration in seconds. This represents the quantity of audio data to return 
-            each time the `read` method is invoked. If `block_dur` is 0.025 (i.e. 25 ms) and the sampling
-            rate is 8000 and the sample width is 2 bytes, `read` returns a buffer of 0.025 * 8000 * 2 = 400
+            each time the :func:`read` method is invoked. If `block_dur` is 0.025 (i.e. 25 ms) and the sampling
+            rate is 8000 and the sample width is 2 bytes, :func:`read` returns a buffer of 0.025 * 8000 * 2 = 400
             bytes at most. This parameter will be looked for (and used if available) before `block_size`.
             If neither parameter is given, `block_dur` will be set to 0.01 second (i.e. 10 ms)
             
             
         `hop_dur`, `hd` : *(float)*
             quantity of data to skip from current processing window. if `hop_dur` is supplied then there
-            will be an overlap of `block_dur` - `hop_dur` between two adjacent processing windows. This
+            will be an overlap of `block_dur` - `hop_dur` between two adjacent blocks. This
             parameter will be looked for (and used if available) before `hop_size`. If neither parameter
             is given, `hop_dur` will be set to `block_dur` which means that there will be no overlap
-            between adjacent windows.
+            between two consecutively read blocks.
              
           
-        `block_size`,`bs` : *(int)*
+        `block_size`, `bs` : *(int)*
             number of samples to read each time the `read` method is called. Default: a block size
             that represents a window of 10ms, so for a sampling rate of 16000, the default `block_size`
             is 160 samples, for a rate of 44100, `block_size` = 441 samples, etc.
@@ -279,11 +303,150 @@
         `hop_size`, `hs` : *(int)*
             determines the number of overlapping samples between two adjacent read windows. For a
             `hop_size` of value *N*, the overlap is `block_size` - *N*. Default : `hop_size` = `block_size`,
-            means that there is no overlap.       
+            means that there is no overlap.
+            
+        :Returns:
+        
+        An AudioDataSource object that has the desired features.
+        
+        :Exampels:
+        
+        1. **Create an AudioDataSource that reads data from the microphone (requires Pyaudio) with default audio parameters:**
+        
+        .. code:: python
+        
+            from auditok import ADSFactory
+            ads = ADSFactory.ads()
+            ads.get_sampling_rate()
+            16000
+            ads.get_sample_width()
+            2
+            ads.get_channels()
+            1
+        
+        
+        2. **Create an AudioDataSource that reads data from the microphone with a sampling rate of 48KHz:**
+        
+        .. code:: python
+        
+            from auditok import ADSFactory
+            ads = ADSFactory.ads(sr=48000)
+            ads.get_sampling_rate()
+            48000
+        
+        3. **Create an AudioDataSource that reads data from a wave file:**
+        
+        .. code:: python
+        
+            import auditok
+            from auditok import ADSFactory
+            ads = ADSFactory.ads(fn=auditok.dataset.was_der_mensch_saet_mono_44100_lead_trail_silence)
+            ads.get_sampling_rate()
+            44100
+            ads.get_sample_width()
+            2
+            ads.get_channels()
+            1
+        
+        4. **Define size of read blocks as 20 ms**
+        
+        .. code:: python
+        
+            import auditok
+            from auditok import ADSFactory
+            '''
+            we know samling rate for previous file is 44100 samples/second
+            so 10 ms are equivalent to 441 samples and 20 ms to 882
+            '''
+            block_size = 882
+            ads = ADSFactory.ads(bs = 882, fn=auditok.dataset.was_der_mensch_saet_mono_44100_lead_trail_silence)
+            ads.open()
+            # read one block
+            data = ads.read()
+            ads.close()
+            len(data)
+            1764
+            assert len(data) ==  ads.get_sample_width() * block_size
+        
+        5. **Define block size as a duration (use block_dur or bd):**
+        
+        .. code:: python
+        
+            import auditok
+            from auditok import ADSFactory
+            dur = 0.25 # second
+            ads = ADSFactory.ads(bd = dur, fn=auditok.dataset.was_der_mensch_saet_mono_44100_lead_trail_silence)
+            '''
+            we know samling rate for previous file is 44100 samples/second
+            for a block duration of 250 ms, block size should be 0.25 * 44100 = 11025
+            '''
+            ads.get_block_size()
+            11025
+            assert ads.get_block_size() ==  int(0.25 * 44100)
+            ads.open()
+            # read one block
+            data = ads.read()
+            ads.close()
+            len(data)
+            22050
+            assert len(data) ==  ads.get_sample_width() * ads.get_block_size()
+            
+        6. **Read overlapping blocks (one of hope_size, hs, hop_dur or hd > 0):**
+        
+        For better readability we'd better use :class:`auditok.io.BufferAudioSource` with a string buffer:
+
+        .. code:: python
+
+            import auditok
+            from auditok import ADSFactory
+            '''
+            we supply a data beffer instead of a file (keyword 'bata_buffer' or 'db')
+            sr : sampling rate = 16 samples/sec
+            sw : sample width = 1 byte
+            ch : channels = 1
+            '''
+            buffer = "abcdefghijklmnop" # 16 bytes = 1 second of data
+            bd = 0.250 # block duration = 250 ms = 4 bytes
+            hd = 0.125 # hop duration = 125 ms = 2 bytes 
+            ads = ADSFactory.ads(db = "abcdefghijklmnop", bd = bd, hd = hd, sr = 16, sw = 1, ch = 1)
+            ads.open()
+            ads.read()
+            'abcd'
+            ads.read()
+            'cdef'
+            ads.read()
+            'efgh'
+            ads.read()
+            'ghij'
+            data = ads.read()
+            assert data == 'ijkl'
+        
+        7. **Limit amount of read data (use max_time or mt):**
+        
+        .. code:: python
+        
+            '''
+            We know audio file is larger than 2.25 seconds
+            We want to read up to 2.25 seconds of audio data
+            '''
+            ads = ADSFactory.ads(mt = 2.25, fn=auditok.dataset.was_der_mensch_saet_mono_44100_lead_trail_silence)
+            ads.open()
+            data = []
+            while True:
+                d = ads.read()
+                if d is None:
+                    break
+                data.append(d)
+                
+            ads.close()
+            data = b''.join(data)
+            assert len(data) == int(ads.get_sampling_rate() * 2.25 * ads.get_sample_width() * ads.get_channels())
         
         """
         
         
+        
+        
         ADSFactory._check_normalize_args(kwargs)
         
         block_dur = kwargs.pop("bd")
@@ -358,6 +521,10 @@
         
         
     class AudioDataSource(DataSource):
+        """
+        Base class for AudioDataSource objects.
+        It inherits from DataSource and encapsulates an AudioSource object.
+        """
         
         def __init__(self, audio_source, block_size):
             
@@ -414,6 +581,9 @@
     
     
     class ADSDecorator(AudioDataSource):
+        """
+        Base decorator class for AudioDataSource objects.
+        """
         __metaclass__ = ABCMeta
         
         def __init__(self, ads):
@@ -455,7 +625,7 @@
     class OverlapADS(ADSDecorator):
         
         """
-        Read overlapping audio frames
+        A class for AudioDataSource objects that can read and return overlapping audio frames
         """
         
         def __init__(self, ads, hop_size):
@@ -526,6 +696,10 @@
     
     
     class LimiterADS(ADSDecorator):
+        """
+        A class for AudioDataSource objects that can read a fixed amount of data.
+        This can be useful when reading data from the microphone or from large audio files.
+        """
         
         def __init__(self, ads, max_time):
             ADSFactory.ADSDecorator.__init__(self, ads)
@@ -557,6 +731,10 @@
       
     
     class RecorderADS(ADSDecorator):
+        """
+        A class for AudioDataSource objects that can record all audio data they read,
+        with a rewind facility.
+        """
         
         def __init__(self, ads):
             ADSFactory.ADSDecorator.__init__(self, ads)
@@ -630,6 +808,20 @@
             
 
 class AudioEnergyValidator(DataValidator):
+    """
+    The most basic auditok audio frame validator.
+    This validator computes the log energy of an input audio frame
+    and return True if the result is >= a given threshold, False 
+    otherwise.
+    
+    :Parameters:
+    `sample_width` : int
+        Number of bytes of one audio sample. This is used to convert data from `basestring` or `Bytes` to
+        an array of floats.
+        
+    `energy_threshold` : float
+        A threshold used to check whether an input data buffer is valid. 
+    """
     
     
     if _WITH_NUMPY:
@@ -676,12 +868,35 @@
             
     
     def __init__(self, sample_width, energy_threshold=45):
-        
         self.sample_width = sample_width
         self._energy_threshold = energy_threshold
         
             
     def is_valid(self, data):
+        """
+        Check if data is valid. Audio data will be converted into an array (of
+        signed values) of which the log energy is computed. Log energy is computed
+        as follows:
+        
+        .. code:: python
+        
+            arr = AudioEnergyValidator._convert(signal, sample_width)
+            energy = float(numpy.dot(arr, arr)) / len(arr)
+            log_energy = 10. * numpy.log10(energy)
+        
+        
+        :Parameters:
+        
+            `data` : either a string or a Bytes buffer
+                `data` is converted into a numerical arra using the `sample_width`
+                given in the constructor.
+        
+        :Retruns:
+        
+            True if `log_energy` > `energy_threshold`, False otherwise.
+        """
+        
+        
         signal = AudioEnergyValidator._convert(data, self.sample_width)
         return AudioEnergyValidator._signal_log_energy(signal) >= self._energy_threshold
     
--- a/demos/audio_tokenize_demo.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/demos/audio_tokenize_demo.py	Tue Dec 01 20:13:02 2015 +0100
@@ -23,7 +23,6 @@
    tokens = tokenizer.tokenize(asource)
 
    # Play detected regions back
-
    player = player_for(asource)
 
    # Rewind and read the whole signal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/apitutorial.rst	Tue Dec 01 20:13:02 2015 +0100
@@ -0,0 +1,528 @@
+`auditok` API Tutorial
+======================
+
+.. contents:: `Contents`
+   :depth: 3
+
+
+**auditok**  is a module that can be used as a generic tool for data
+tokenization. Although its core motivation is **Acoustic Activity 
+Detection** (AAD) and extraction from audio streams (i.e. detect
+where a noise/an acoustic activity occurs within an audio stream and
+extract the corresponding portion of signal), it can easily be
+adapted to other tasks.
+
+Globally speaking, it can be used to extract, from a sequence of
+observations, all sub-sequences that meet a certain number of
+criteria in terms of:
+
+1. Minimum length of a **valid** token (i.e. sub-sequence)
+2. Maximum length of a valid token
+3. Maximum tolerated consecutive **non-valid** observations within
+   a valid token
+
+Examples of a non-valid observation are: a non-numeric ascii symbol
+if you are interested in sub-sequences of numeric symbols, or a silent
+audio window (of 10, 20 or 100 milliseconds for instance) if what
+interests you are audio regions made up of a sequence of "noisy"
+windows (whatever kind of noise: speech, baby cry, laughter, etc.).
+
+The most important component of `auditok` is the :class:`auditok.core.StreamTokenizer`
+class. An instance of this class encapsulates a :class:`auditok.util.DataValidator` and can be 
+configured to detect the desired regions from a stream.
+The :func:`auditok.core.StreamTokenizer.tokenize` method accepts a :class:`auditok.util.DataSource`
+object that has a `read` method. Read data can be of any type accepted
+by the `validator`.
+
+
+As the main aim of this module is **Audio Activity Detection**,
+it provides the :class:`auditok.util.ADSFactory` factory class that makes
+it very easy to create an :class:`auditok.util.ADSFactory.AudioDataSource`
+(a class that implements :class:`auditok.util.DataSource`) object, be that from:
+
+- A file on the disk
+- A buffer of data
+- The built-in microphone (requires PyAudio)
+ 
+
+The :class:`auditok.util.ADSFactory.AudioDataSource` class inherits from
+:class:`auditok.util.DataSource` and supplies a higher abstraction level
+than :class:`auditok.io.AudioSource` thanks to a bunch of handy features:
+
+- Define a fixed-length `block_size` (alias `bs`, i.e. analysis window)
+- Alternatively, use `block_dur` (duration in seconds, alias `bd`)
+- Allow overlap between two consecutive analysis windows
+  (if one of `hop_size` , `hs` or `hop_dur` , `hd` keywords is used and is > 0 and < `block_size`).
+  This can be very important if your validator use the **spectral** information of audio data
+  instead of raw audio samples.
+- Limit the amount (i.e. duration) of read data (if keyword `max_time` or `mt` is used, very useful when reading data from the microphone)
+- Record all read data and rewind if necessary (if keyword `record` or `rec` , also useful if you read data from the microphone and
+  you want to process it many times off-line and/or save it)  
+
+See :class:`auditok.util.ADSFactory` documentation for more information.
+
+Last but not least, the current version has only one audio window validator based on
+signal energy (:class:`auditok.util.AudioEnergyValidator).
+
+**********************************
+Illustrative examples with strings
+**********************************
+
+Let us look at some examples using the :class:`auditok.util.StringDataSource` class
+created for test and illustration purposes. Imagine that each character of 
+:class:`auditok.util.StringDataSource` data represent an audio slice of 100 ms for
+example. In the following examples we will use upper case letters to represent
+noisy audio slices (i.e. analysis windows or frames) and lower case letter for
+silent frames.
+
+
+Extract sub-sequences of consecutive upper case letters
+#######################################################
+
+
+We want to extract sub-sequences of characters that have:
+    
+- A minimum length of 1 (`min_length` = 1)
+- A maximum length of 9999 (`max_length` = 9999)
+- Zero consecutive lower case characters within them (`max_continuous_silence` = 0)
+
+We also create the `UpperCaseChecker` with a `read` method that returns `True` if the 
+checked character is in upper case and `False` otherwise. 
+
+.. code:: python
+      
+    from auditok import StreamTokenizer, StringDataSource, DataValidator
+    
+    class UpperCaseChecker(DataValidator):
+       def is_valid(self, frame):
+          return frame.isupper()
+    
+    dsource = StringDataSource("aaaABCDEFbbGHIJKccc")
+    tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
+                 min_length=1, max_length=9999, max_continuous_silence=0)
+                 
+    tokenizer.tokenize(dsource)
+
+The output is a list of two tuples, each contains the extracted sub-sequence and its
+start and end position in the original sequence respectively:
+
+
+.. code:: python
+
+    
+    [(['A', 'B', 'C', 'D', 'E', 'F'], 3, 8), (['G', 'H', 'I', 'J', 'K'], 11, 15)]
+    
+
+Tolerate up to two non-valid (lower case) letters within an extracted sequence
+##############################################################################
+
+To do so, we set `max_continuous_silence` =2:
+
+.. code:: python
+
+
+    from auditok import StreamTokenizer, StringDataSource, DataValidator
+    
+    class UpperCaseChecker(DataValidator):
+       def is_valid(self, frame):
+          return frame.isupper()
+    
+    dsource = StringDataSource("aaaABCDbbEFcGHIdddJKee")
+    tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
+                 min_length=1, max_length=9999, max_continuous_silence=2)
+                 
+    tokenizer.tokenize(dsource)
+
+
+output:
+
+.. code:: python
+  
+    [(['A', 'B', 'C', 'D', 'b', 'b', 'E', 'F', 'c', 'G', 'H', 'I', 'd', 'd'], 3, 16), (['J', 'K', 'e', 'e'], 18, 21)]
+    
+Notice the trailing lower case letters "dd" and "ee" at the end of the two
+tokens. The default behavior of :class:`auditok.core.StreamTokenizer` is to keep the *trailing
+silence* if it doesn't exceed `max_continuous_silence`. This can be changed
+using the `StreamTokenizer.DROP_TRAILING_SILENCE` mode (see next example).
+
+Remove trailing silence
+#######################
+
+Trailing silence can be useful for many sound recognition applications, including
+speech recognition. Moreover, from the human auditory system point of view, trailing
+low energy signal helps removing abrupt signal cuts.
+
+If you want to remove it anyway, you can do it by setting `mode` to `StreamTokenizer.DROP_TRAILING_SILENCE`:
+
+.. code:: python
+
+    from auditok import StreamTokenizer, StringDataSource, DataValidator
+    
+    class UpperCaseChecker(DataValidator):
+       def is_valid(self, frame):
+          return frame.isupper()
+    
+    dsource = StringDataSource("aaaABCDbbEFcGHIdddJKee")
+    tokenizer = StreamTokenizer(validator=UpperCaseChecker(), 
+                 min_length=1, max_length=9999, max_continuous_silence=2,
+                 mode=StreamTokenizer.DROP_TRAILING_SILENCE)
+                 
+    tokenizer.tokenize(dsource)
+
+output:
+
+.. code:: python
+
+    [(['A', 'B', 'C', 'D', 'b', 'b', 'E', 'F', 'c', 'G', 'H', 'I'], 3, 14), (['J', 'K'], 18, 19)]
+
+
+
+Limit the length of detected tokens
+###################################
+
+
+Imagine that you just want to detect and recognize a small part of a long
+acoustic event (e.g. engine noise, water flow, etc.) and avoid that that 
+event hogs the tokenizer and prevent it from feeding the event to the next
+processing step (i.e. a sound recognizer). You can do this by:
+
+ - limiting the length of a detected token.
+ 
+ and
+ 
+ - using a callback function as an argument to :class:`auditok.core.StreamTokenizer.tokenize`
+   so that the tokenizer delivers a token as soon as it is detected.
+
+The following code limits the length of a token to 5:
+
+.. code:: python
+    
+    from auditok import StreamTokenizer, StringDataSource, DataValidator
+    
+    class UpperCaseChecker(DataValidator):
+       def is_valid(self, frame):
+          return frame.isupper()
+    
+    dsource = StringDataSource("aaaABCDEFGHIJKbbb")
+    tokenizer = StreamTokenizer(validator=UpperCaseChecker(),
+                 min_length=1, max_length=5, max_continuous_silence=0)
+                 
+    def print_token(data, start, end):
+        print("token = '{0}', starts at {1}, ends at {2}".format(''.join(data), start, end))
+                 
+    tokenizer.tokenize(dsource, callback=print_token)
+    
+
+output:
+
+.. code:: python
+
+    "token = 'ABCDE', starts at 3, ends at 7"
+    "token = 'FGHIJ', starts at 8, ends at 12"
+    "token = 'K', starts at 13, ends at 13"
+
+
+************************
+`auditok` and Audio Data
+************************
+
+In this section we will use :class:`auditok.util.ADSFactory`, :class:`auditok.util.AudioEnergyValidator` 
+and :class:`auditok.core.StreamTokenizer` for an AAD demonstration using audio data. Before we get any
+further it is worth, explaining a certain number of points.
+
+:func:`auditok.util.ADSFactory.ads` method is called to create an 
+:class:`auditok.util.ADSFactory.AudioDataSource` object that can be1
+passed to  :func:`auditok.core.StreamTokenizer.tokenize`. :func:`auditok.util.ADSFactory.ads`
+accepts a number of keyword arguments, of which none is mandatory. The returned
+:class:`auditok.util.ADSFactory.AudioDataSource` object's features and behavior can however greatly differ 
+depending on the passed arguments. Further details can be found in the respective
+method documentation. Note however the following two calls that will
+create an :class:`auditok.util.ADSFactory.AudioDataSource` that read data from an
+audio file and from the built-in microphone respectively.
+
+.. code:: python
+    
+    from auditok import ADSFactory
+    
+    # Get an AudioDataSource from a file
+    file_ads = ADSFactory.ads(filename = "path/to/file/")
+    
+    # Get an AudioDataSource from the built-in microphone
+    # The returned object has the default values for sampling
+    # rate, sample width an number of channels. see method's
+    # documentation for customized values 
+    mic_ads = ADSFactory.ads()
+    
+For `StreamTkenizer`, parameters `min_length`, `max_length` and `max_continuous_silence`
+are expressed in term of number of frames. If you want a `max_length` of *2 seconds* for
+your detected sound events and your *analysis window* is *10 ms* long, you have to specify
+a `max_length` of 200 (`int(2. / (10. / 1000)) == 200`). For a `max_continuous_silence` of *300 ms*
+for instance, the value to pass to StreamTokenizer is 30 (`int(0.3 / (10. / 1000)) == 30`).
+
+
+Where do you get the size of the **analysis window** from?
+
+
+Well this is a parameter you pass to `ADSFactory.ads`. By default `ADSFactory.ads` uses
+an analysis window of 10 ms. the number of samples that 10 ms of signal contain will
+vary depending on the sampling rate of your audio source (file, microphone, etc.).
+For a sampling rate of 16KHz (16000 samples per second), we have 160 samples for 10 ms.
+Therefore you can use block sizes of 160, 320, 1600 for analysis windows of 10, 20 and 100 
+ms respectively.
+
+.. code:: python
+    
+    from auditok import ADSFactory
+    
+    file_ads = ADSFactory.ads(filename = "path/to/file/", block_size = 160)
+    
+    file_ads = ADSFactory.ads(filename = "path/to/file/", block_size = 320)
+    
+    # If no sampling rate is specified, ADSFactory use 16KHz as the default
+    # rate for the microphone. If you want to use a window of 100 ms, use 
+    # a block size of 1600 
+    mic_ads = ADSFactory.ads(block_size = 1600)
+    
+So if your not sure what you analysis windows in seconds is, use the following:
+
+.. code:: python
+    
+    my_ads = ADSFactory.ads(...)
+    analysis_win_seconds = float(my_ads.get_block_size()) / my_ads.get_sampling_rate()
+    analysis_window_ms = analysis_win_seconds * 1000
+    
+    # For a `max_continuous_silence` of 300 ms use:
+    max_continuous_silence = int(300. / analysis_window_ms)
+    
+    # Which is the same as
+    max_continuous_silence = int(0.3 / (analysis_window_ms / 1000))
+    
+
+******************************
+Examples using real audio data
+******************************
+
+
+Extract isolated phrases from an utterance
+##########################################
+
+We will build an :class:`auditok.util.ADSFactory.AudioDataSource` using a wave file from 
+the database. The file contains of isolated pronunciation of digits from 1 to 1
+in Arabic as well as breath-in/out between 2 and 3. The code will play the
+original file then the detected sounds separately. Note that we use an 
+`energy_threshold` of 65, this parameter should be carefully chosen. It depends
+on microphone quality, background noise and the amplitude of events you want to 
+detect.
+
+.. code:: python
+
+    from auditok import ADSFactory, AudioEnergyValidator, StreamTokenizer, player_for, dataset
+     
+    # We set the `record` argument to True so that we can rewind the source
+    asource = ADSFactory.ads(filename=dataset.one_to_six_arabic_16000_mono_bc_noise, record=True)
+     
+    validator = AudioEnergyValidator(sample_width=asource.get_sample_width(), energy_threshold=65)
+    
+    # Defalut analysis window is 10 ms (float(asource.get_block_size()) / asource.get_sampling_rate())
+    # min_length=20 : minimum length of a valid audio activity is 20 * 10 == 200 ms
+    # max_length=4000 :  maximum length of a valid audio activity is 400 * 10 == 4000 ms == 4 seconds
+    # max_continuous_silence=30 : maximum length of a tolerated  silence within a valid audio activity is 30 * 30 == 300 ms 
+    tokenizer = StreamTokenizer(validator=validator, min_length=20, max_length=400, max_continuous_silence=30)
+    
+    asource.open()
+    tokens = tokenizer.tokenize(asource)
+    
+    # Play detected regions back
+    
+    player = player_for(asource)
+    
+    # Rewind and read the whole signal
+    asource.rewind()
+    original_signal = []
+
+    while True:
+       w = asource.read()
+       if w is None:
+          break
+       original_signal.append(w)
+       
+    original_signal = ''.join(original_signal)
+    
+    print("Playing the original file...")
+    player.play(original_signal)
+    
+    print("playing detected regions...")
+    for t in tokens:
+        print("Token starts at {0} and ends at {1}".format(t[1], t[2]))
+        data = ''.join(t[0])
+        player.play(data)
+        
+    assert len(tokens) == 8
+    
+
+The tokenizer extracts 8 audio regions from the signal, including all isolated digits
+(from 1 to 6) as well as the 2-phase respiration of the subject. You might have noticed
+that, in the original file, the last three digit are closer to each other than the 
+previous ones. If you wan them to be extracted as one single phrase, you can do so
+by tolerating a larger continuous silence within a detection:
+ 
+.. code:: python
+    
+    tokenizer.max_continuous_silence = 50
+    asource.rewind()
+    tokens = tokenizer.tokenize(asource)
+    
+    for t in tokens:
+       print("Token starts at {0} and ends at {1}".format(t[1], t[2]))
+       data = ''.join(t[0])
+       player.play(data)
+    
+    assert len(tokens) == 6
+        
+         
+Trim leading and trailing silence
+#################################
+ 
+The  tokenizer in the following example is set up to remove the silence
+that precedes the first acoustic activity or follows the last activity 
+in a record. It preserves whatever it founds between the two activities.
+In other words, it removes the leading and trailing silence.
+
+Sampling rate is 44100 sample per second, we'll use an analysis window of 100 ms
+(i.e. block_size == 4410)
+
+Energy threshold is 50.
+
+The tokenizer will start accumulating windows up from the moment it encounters
+the first analysis window of an energy >= 50. ALL the following windows will be 
+kept regardless of their energy. At the end of the analysis, it will drop trailing
+windows with an energy below 50.
+
+This is an interesting example because the audio file we're analyzing contains a very
+brief noise that occurs within the leading silence. We certainly do want our tokenizer 
+to stop at this point and considers whatever it comes after as a useful signal.
+To force the tokenizer to ignore that brief event we use two other parameters `init_min`
+ans `init_max_silence`. By `init_min` = 3 and `init_max_silence` = 1 we tell the tokenizer
+that a valid event must start with at least 3 noisy windows, between which there
+is at most 1 silent window.
+
+Still with this configuration we can get the tokenizer detect that noise as a valid event
+(if it actually contains 3 consecutive noisy frames). To circumvent this we use an enough
+large analysis window (here of 100 ms) to ensure that the brief noise be surrounded by a much
+longer silence and hence the energy of the overall analysis window will be below 50.
+
+When using a shorter analysis window (of 10ms for instance, block_size == 441), the brief
+noise contributes more to energy calculation which yields an energy of over 50 for the window.
+Again we can deal with this situation by using a higher energy threshold (55 for example).
+
+.. code:: python
+
+    from auditok import ADSFactory, AudioEnergyValidator, StreamTokenizer, player_for, dataset
+
+    # record = True so that we'll be able to rewind the source.
+    asource = ADSFactory.ads(filename=dataset.was_der_mensch_saet_mono_44100_lead_trail_silence,
+             record=True, block_size=4410)
+    asource.open()
+
+    original_signal = []
+    # Read the whole signal
+    while True:
+       w = asource.read()
+       if w is None:
+          break
+       original_signal.append(w)
+    
+    original_signal = ''.join(original_signal)
+    
+    # rewind source
+    asource.rewind()
+    
+    # Create a validator with an energy threshold of 50
+    validator = AudioEnergyValidator(sample_width=asource.get_sample_width(), energy_threshold=50)
+    
+    # Create a tokenizer with an unlimited token length and continuous silence within a token
+    # Note the DROP_TRAILING_SILENCE mode that will ensure removing trailing silence
+    trimmer = StreamTokenizer(validator, min_length = 20, max_length=99999999, init_min=3, init_max_silence=1, max_continuous_silence=9999999, mode=StreamTokenizer.DROP_TRAILING_SILENCE)
+    
+    
+    tokens = trimmer.tokenize(asource)
+    
+    # Make sure we only have one token
+    assert len(tokens) == 1, "Should have detected one single token"
+    
+    trimmed_signal = ''.join(tokens[0][0])
+    
+    player = player_for(asource)
+    
+    print("Playing original signal (with leading and trailing silence)...")
+    player.play(original_signal)
+    print("Playing trimmed signal...")
+    player.play(trimmed_signal)
+    
+
+Online audio signal processing
+##############################
+
+In the next example, audio data is directly acquired from the built-in microphone.
+The :func:`auditok.core.StreamTokenizer.tokenize` method is passed a callback function
+so that audio activities are delivered as soon as they are detected. Each detected
+activity is played back using the build-in audio output device.
+
+As mentioned before , Signal energy is strongly related to many factors such
+microphone sensitivity, background noise (including noise inherent to the hardware), 
+distance and your operating system sound settings. Try a lower `energy_threshold`
+if your noise does not seem to be detected and a higher threshold if you notice
+an over detection (echo method prints a detection where you have made no noise).
+
+.. code:: python
+
+    from auditok import ADSFactory, AudioEnergyValidator, StreamTokenizer, player_for
+     
+    # record = True so that we'll be able to rewind the source.
+    # max_time = 10: read 10 seconds from the microphone
+    asource = ADSFactory.ads(record=True, max_time=10)
+    
+    validator = AudioEnergyValidator(sample_width=asource.get_sample_width(), energy_threshold=50)
+    tokenizer = StreamTokenizer(validator=validator, min_length=20, max_length=250, max_continuous_silence=30)
+    
+    player = player_for(asource)
+    
+    def echo(data, start, end):
+       print("Acoustic activity at: {0}--{1}".format(start, end))
+       player.play(''.join(data))
+       
+    asource.open()
+    
+    tokenizer.tokenize(asource, callback=echo)
+
+If you want to re-run the tokenizer after changing of one or many parameters, use the following code:
+
+.. code:: python
+
+    asource.rewind()
+    # change energy threshold for example
+    tokenizer.validator.set_energy_threshold(55)
+    tokenizer.tokenize(asource, callback=echo)
+
+In case you want to play the whole recorded signal back use:
+
+.. code:: python
+
+    player.play(asource.get_audio_source().get_data_buffer())
+    
+
+************
+Contributing
+************
+
+**auditok** is on `GitHub <https://github.com/amsehili/auditok>`_. You're welcome to fork it and contribute.
+
+
+Amine SEHILI <amine.sehili@gmail.com>
+September 2015
+
+*******
+License
+*******
+
+This package is published under GNU GPL Version 3.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/cmdline.rst	Tue Dec 01 20:13:02 2015 +0100
@@ -0,0 +1,347 @@
+`auditok` Command-line Usage Guide
+==================================
+
+This user guide will go through a few of the most useful operations you can use **auditok** for and present two practical use cases. 
+
+
+.. contents:: `Contents`
+   :depth: 3
+
+
+**********************
+Two-figure explanation
+**********************
+
+The following two figures illustrate an audio signal (blue) and regions detected as valid audio activities (green rectangles) according to a given threshold (red dashed line). They respectively depict the detection result when:
+
+1. the detector tolerates phases of silence of up to 0.3 second (300 ms) within an audio activity (also referred to as acoustic event):
+
+.. figure:: figures/figure_1.png
+    :align: center
+    :alt: alternate text
+    :figclass: align-center
+
+2. the detector splits an audio activity event into many activities if the within activity silence is over 0.2 second:
+
+.. figure:: figures/figure_2.png
+    :align: center
+    :alt: alternate text
+    :figclass: align-center
+
+
+******************
+Command line usage
+******************
+
+Try the detector with your voice
+################################
+
+The first thing you want to check is perhaps how `auditok` detects your voice. If you have installed `PyAudio` just run (`Ctrl-C` to stop):
+
+.. code:: bash
+
+    auditok
+
+This will print **id** **start time** and **end time** for each detected activity. If you don't have `PyAudio`, you can use `sox` for data acquisition (`sudo apt-get install sox`) and tell `auditok` to read data from standard input:
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -i - -r 16000 -w 2 -c 1
+    
+Note that when data is read from standard input the same audio parameters must be used for both `sox` (or any other data generation/acquisition tool) and `auditok`. The following table summarizes audio parameters.
+
+
++-----------------+------------+----------------+-----------------------+
+| Audio parameter | sox option | auditok option | `auditok` default     |
++=================+============+================+=======================+
+| Sampling rate   |     -r     |       -r       |      16000            |
++-----------------+------------+----------------+-----------------------+
+| Sample width    |  -b (bits) |     -w (bytes) |      2                |
++-----------------+------------+----------------+-----------------------+
+| Channels        |  -c        |     -c         |      1                |
++-----------------+------------+----------------+-----------------------+
+| Encoding        |  -e        |     None       | always signed integer |
++-----------------+------------+----------------+-----------------------+
+
+According to this table, the previous command can be run as:
+
+.. code:: bash
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -i -
+
+Play back detections
+####################
+
+.. code:: bash
+
+    auditok -E
+
+OR
+
+.. code:: bash
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -i - -E
+
+Option `-E` stands for echo, so `auditok` plays back whatever it detects. Using `-E` requires `PyAudio`, if you don't have `PyAudio` and want to play detections with sox, use the `-C` option:
+
+.. code:: bash
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -i - -C "play -q -t raw -r 16000 -c 1 -b 16 -e signed $"
+    
+The `-C` option tells `auditok` to interpret its content as a command that should be run whenever `auditok` detects an audio activity, replacing the `$` by a name of a temporary file into which the activity is saved as raw audio. Here we use `play` to play the activity, giving the necessary `play` arguments for raw data.
+
+`rec` and `play` are just an alias for `sox`.
+
+The `-C` option can be useful in many cases. Imagine a command that sends audio data over a network only if there is an audio activity and saves bandwidth during silence.
+
+Set detection threshold
+#######################
+
+If you notice that there are too many detections, use a higher value for energy threshold (the current version only implements a `validator` based on energy threshold. The use of spectral information is also desirable and might be part of future releases). To change the energy threshold (default: 50), use option `-e`:
+
+.. code:: bash
+
+    auditok -E -e 55
+
+OR
+
+.. code:: bash
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -i - -e 55 -C "play -q -t raw -r 16000 -c 1 -b 16 -e signed $"
+
+If however you figure out that the detector is missing some of or all your audio activities, use a lower value for `-e`.
+
+Set format for printed detections information
+#############################################
+
+By default, `auditok` prints the `id` `start time` `end time` of each detected activity:
+
+.. code:: bash
+
+    1 1.87 2.67
+    2 3.05 3.73
+    3 3.97 4.49
+    ...
+    
+If you want to personalize the output format, use `--printf` option:
+
+    auditok -e 55 --printf "[{id}]: {start} to {end}"
+
+Output:
+
+.. code:: bash
+
+    [1]: 0.22 to 0.67
+    [2]: 2.81 to 4.18
+    [3]: 5.53 to 6.44
+    [4]: 7.32 to 7.82
+    ...
+
+Keywords `{id}`, `{start}` and `{end}` can be placed and repeated anywhere in the text. Time is shown in seconds, if you want a more detailed time information, use `--time-format`:
+
+    auditok -e 55 --printf "[{id}]: {start} to {end}" --time-format "%h:%m:%s.%i"
+    
+Output:
+
+.. code:: bash
+
+    [1]: 00:00:01.080 to 00:00:01.760
+    [2]: 00:00:02.420 to 00:00:03.440
+    [3]: 00:00:04.930 to 00:00:05.570
+    [4]: 00:00:05.690 to 00:00:06.020
+    [5]: 00:00:07.470 to 00:00:07.980
+    ...
+
+Valid time directives are: `%h` (hours) `%m` (minutes) `%s` (seconds) `%i` (milliseconds). Two other directives, `%S` (default) and `%I` can be used for absolute time in seconds and milliseconds respectively.
+
+1st Practical use case example: generate a subtitles template
+#############################################################
+
+Using `--printf ` and `--time-format`, the following command, used with an input audio or video file, will generate and an **srt** file template that can be later edited with a subtitles editor in a way that reduces the time needed to define when each utterance starts and where it ends: 
+
+.. code:: bash
+
+    auditok -e 55 -i input.wav -m 10 --printf "{id}\n{start} --> {end}\nPut some text here...\n" --time-format "%h:%m:%s.%i"
+
+Output:
+
+.. code:: bash
+
+    1
+    00:00:00.730 --> 00:00:01.460
+    Put some text here...
+    
+    2
+    00:00:02.440 --> 00:00:03.900
+    Put some text here...
+
+    3
+    00:00:06.410 --> 00:00:06.970
+    Put some text here...
+
+    4
+    00:00:07.260 --> 00:00:08.340
+    Put some text here...
+
+    5
+    00:00:09.510 --> 00:00:09.820
+    Put some text here...
+
+
+2nd Practical use case example: build ab (very) basic voice control application
+###############################################################################
+
+`This repository <https://github.com/amsehili/gspeech-rec>`_ supplies a bash script the can send audio data to Google's
+Speech Recognition service and get its transcription. In the following we will use **auditok** as a lower layer component
+of a voice control application. The basic idea is to tell **auditok** to run, for each detected audio activity, a certain
+number of commands that make up the rest of our voice control application.
+
+Assume you have installed **sox** and downloaded the Speech Recognition script. The sequence of commands to run is:
+
+1- Convert raw audio data to flac using **sox**:
+
+.. code:: bash
+
+    sox -t raw -r 16000 -c 1 -b 16 -e signed raw_input output.flac
+
+2- Send falc audio to google and get its filtred transcription using `speech-rec.sh <https://github.com/amsehili/gspeech-rec/blob/master/speech-rec.sh>`_ :
+
+.. code:: bash
+
+    speech-rec.sh -i output.flac -r 16000
+    
+3- Use **grep** to select lines that coantain *transcript*:
+
+.. code:: bash
+
+    grep transcript
+
+
+4- Launch the followin script, giving it the transcription as input:
+
+.. code:: bash
+
+    #!/bin/bash
+
+    read line
+
+    RES=`echo "$line" | grep -i "open firefox"`
+
+    if [[ $RES ]]
+       then
+         echo "Launch command: 'firefox &' ... "
+         firefox &
+         exit 0
+    fi
+
+    exit 0
+
+As you can see, the script can handle one single voice command. It runs firefox if the text it receives contains **run firefox**.
+Save a script into a file named voice-control.sh (don't forget to run a **chmod u+x voice-control.sh**).
+
+Now, thanks to option `-C`, we will use the three instructions with a pipe and tell auditok to run them for every time it detects
+an audio activity. Try the following command and say *open firefox*:
+
+
+.. code:: bash
+
+    rec -q -t raw -r 16000 -c 1 -b 16 -e signed - | auditok -M 5 -m 3 -n 1 --debug-file log -e 60 -C "sox -t raw -r 16000 -c 1 -b 16 -e signed $ audio.flac ; speech-rec.sh -i audio.flac -r 16000 | grep transcript | ./voice-control.sh"
+
+
+
+
+Plot signal and detections
+##########################
+
+use option `-p`. Requires `matplotlib` and `numpy`.
+
+.. code:: bash
+
+    auditok ...  -p
+
+
+Save plot as image or PDF
+#########################
+
+.. code:: bash
+
+    auditok ...  --save-image output.png
+
+Requires `matplotlib` and `numpy`. Accepted formats: eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff.
+
+
+Read data from file
+###################
+
+.. code:: bash
+
+    auditok -i input.wav ...
+
+Install `pydub` for other audio formats.
+
+
+Limit the length of acquired data
+#################################
+
+.. code:: bash
+
+    auditok -M 12 ...
+
+Time is in seconds.
+
+
+Save the whole acquired audio signal
+####################################
+
+.. code:: bash
+
+    auditok -O output.wav ...
+
+Install `pydub` for other audio formats.
+
+
+Save each detection into a separate audio file
+##############################################
+
+.. code:: bash
+
+    auditok -o det_{N}_{start}_{end}.wav ...
+
+You can use a free text and place `{N}`, `{start}` and `{end}` wherever you want, they will be replaced by detection number, start time and end time respectively. Another example:
+
+.. code:: bash
+
+    auditok -o {start}-{end}.wav ...
+    
+Install `pydub` for more audio formats.
+
+
+Setting detection parameters
+############################
+
+Alongside the threshold option `-e` seen so far, a couple of other options can have a great impact on the detector behavior. These options are summarized in the following table:
+
++--------+-------------------------------------------------------+---------+------------------+
+| Option | Description                                           | Unit    | Default          |
++========+=======================================================+=========+==================+
+| `-n`   | Minimum length an accepted audio activity should have | second  |   0.2 (200 ms)   |
++--------+-------------------------------------------------------+---------+------------------+
+| `-m`   | Maximum length an accepted audio activity should reach| second  |   5.             |
++--------+-------------------------------------------------------+---------+------------------+
+| `-s`   | Maximum length of a continuous silence period within  | second  |   0.3 (300 ms)   |
+|        | an accepted audio activity                            |         |                  |
++--------+-------------------------------------------------------+---------+------------------+
+| `-d`   | Drop trailing silence from an accepted audio activity | boolean |   False          |
++--------+-------------------------------------------------------+---------+------------------+
+| `-a`   | Analysis window length (default value should be good) | second  |   0.01 (10 ms)   |
++--------+-------------------------------------------------------+---------+------------------+
+
+
+*******
+License
+*******
+
+`auditok` is published under the GNU General Public License Version 3.
+
+******
+Author
+******
+Amine Sehili (<amine.sehili@gmail.com>)
--- a/doc/conf.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/doc/conf.py	Tue Dec 01 20:13:02 2015 +0100
@@ -30,9 +30,11 @@
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    'sphinx.ext.viewcode', 'sphinx.ext.autodoc'
+    'sphinx.ext.viewcode', 'sphinx.ext.autodoc', 'sphinx.ext.autosummary'
 ]
 
+sys.path.insert(0, '../auditok/')
+
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
 
@@ -57,9 +59,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '1.2'
+version = '0.1.4'
 # The full version, including alpha/beta/rc tags.
-release = '1.2'
+release = '0.1.4'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -110,7 +112,8 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-#html_theme = 'alabaster'
+#html_theme = 'sphinxdoc'
+
 
 # on_rtd is whether we are on readthedocs.org
 import os
Binary file doc/figures/figure_1.png has changed
Binary file doc/figures/figure_2.png has changed
--- a/doc/index.rst	Sun Nov 29 11:59:57 2015 +0100
+++ b/doc/index.rst	Tue Dec 01 20:13:02 2015 +0100
@@ -1,12 +1,62 @@
-.. include:: ../quickstart.rst
+auditok, an AUDIo TOKenization tool
+===================================
 
-API
+.. image:: https://travis-ci.org/amsehili/auditok.svg?branch=master
+    :target: https://travis-ci.org/amsehili/auditok
+
+**auditok** is an **Audio Activity Detection** tool that can process online data (read from an audio device or from standard input) as well as audio files. It can be used as a command line program and offers an easy to use API.
+
+
+Requirements
+------------
+
+`auditok` can be used with standard Python!
+
+However if you want more features, the following packages are needed:
+
+- `Pydub <https://github.com/jiaaro/pydub>`_ : read audio files of popular audio formats (ogg, mp3, etc.) or extract audio from a video file
+
+- `PyAudio <http://people.csail.mit.edu/hubert/pyaudio/>`_ : read audio data from the microphone and play back detections
+
+- `matplotlib <http://matplotlib.org/>`_ : plot audio signal and detections (see figures above)
+
+- `numpy <http://www.numpy.org>`_ : required by matplotlib. Also used for math operations instead of standard python if available
+
+- Optionally, you can use **sox** or **parecord** for data acquisition and feed **auditok** using a pipe.
+
+Installation
+------------
+
+.. code:: bash
+
+    git clone https://github.com/amsehili/auditok.git
+    cd auditok
+    sudo python setup.py install
+
+
+
+Getting started
+---------------
+
 .. toctree::
     :titlesonly:
-    :maxdepth: 2
+    :maxdepth: 1
 
+       Command-line Usage Guide <cmdline.rst>
+       API Tutorial <apitutorial.rst>
 
 
+API Reference
+-------------
+
+.. toctree::
+    :titlesonly:
+    :maxdepth: 1
+
+       auditok.core <core.rst>
+       auditok.util <util.rst>
+       auditok.io <io.rst>
+       auditok.dataset <dataset.rst>
 
 
 
--- a/doc/util.rst	Sun Nov 29 11:59:57 2015 +0100
+++ b/doc/util.rst	Tue Dec 01 20:13:02 2015 +0100
@@ -2,4 +2,4 @@
 ------------
 
 .. automodule:: auditok.util
-   :members:
\ No newline at end of file
+   :members:
--- a/setup.py	Sun Nov 29 11:59:57 2015 +0100
+++ b/setup.py	Tue Dec 01 20:13:02 2015 +0100
@@ -16,7 +16,7 @@
    with open('auditok/__init__.py', 'rb') as f:
        version = str(ast.literal_eval(_version_re.search(
        f.read().decode('utf-8')).group(1)))
-       long_desc = open('quickstart.rst', 'rt').read().decode('utf-8')
+       long_desc = open('doc/index.rst', 'rt').read().decode('utf-8')
 
 
 setup(