'''
wav_read_frame_librosa.py
Author: M A Rohit
This program is tested on Ubuntu 18.04 with Python 3.6.9, Numpy 1.19.2, and Librosa 0.8.0.
It requires the installation of the additional package 'librosa' (which can be installed using 'pip install librosa'). The particular function to use is 'librosa.stream()'.

Program flow:
1. open a wav file for reading
2. Next, read audio sequentially in smaller chunks from the wav file, one frame* at a time, in a loop:
     3. load hop_len number of samples of audio
     4. do some processing
     5. write the feature values to a text file

* A "frame" is a chunk of 'hop_len' number of samples, loaded in each iteration. This is distinct from a "window", which is the set of frames stored in the buffer and available for processing in each iteration. The loaded hop_len #samples are appended to the window (on the right side), and hop_len #samples at the start of the window are discarded (akin to the hop between overlapping windows in STFT).

NOTE 1: The naming convention in librosa.stream() is different. The 'frame_length' parameter refers to the window size, and the 'hop_length' refers to the number of loaded samples. 
Additionally, there is a 'block_length' parameter, which sets the number of frames loaded in each iteration, i.e., a 'block_length' x 'hop_length' number of samples are loaded. Setting this parameter to 1 gives us the implementation in 'wav_read_write_frame.py'.

NOTE 2: Writing audio back to another output file is not implemented in this code - librosa has no function for this. But another package 'soundfile' can be used for this, which is similar to the package 'wavefile' used in 'wav_read_write_frame.py'.
'''

import sys
import numpy as np
import librosa

#####Parameters#####
hop_size=10e-3 #10 ms
win_size=50e-3 #50 ms

#####Specify input and output wav files, and output file for features as cmdline args to script#####
in_file = sys.argv[1]
feat_file = sys.argv[2]

#an empty list to store computed feature values, e.g., short-time energy
feat_vals=[]

#get samplerate
samplerate =  librosa.get_samplerate(in_file)

#get window and hop sizes in samples
win_len=int(samplerate*win_size)
hop_len=int(samplerate*hop_size)
block_len=1

#define the generator object, which will yield chunks
stream = librosa.stream(in_file, block_length=block_len, frame_length=win_len, hop_length=hop_len)

#iterate over chunks
for data in stream:	
	#do some processing - e.g., compute short-time energy, and store values
	feat_vals.append((data**2).sum())
		
#Writing the feature values to a text file	
times = np.arange(0, hop_size*len(feat_vals), hop_size)
feats = np.array((times, feat_vals)).T
np.savetxt(feat_file, feats, fmt="%.3f", delimiter='\t', header='Time\tFeature', comments='')
