1 #ifndef BL_BLISS_H_ 2 #define BL_BLISS_H_ 3 4 #include <stdio.h> 5 #include <libavformat/avformat.h> 6 #include <libavutil/md5.h> 7 8 #ifndef M_PI 9 #define M_PI 3.14159265358979323846 10 #endif 11 12 #define BL_VERSION 1.2 13 14 #if LIBAVUTIL_VERSION_MAJOR < 54 15 #define av_frame_alloc avcodec_alloc_frame 16 #define av_frame_unref avcodec_get_frame_defaults 17 #define av_frame_free avcodec_free_frame 18 #endif 19 20 #define BL_LOUD 0 21 #define BL_CALM 1 22 #define BL_UNKNOWN 2 23 #define BL_UNEXPECTED -2 24 #define BL_OK 0 25 26 struct force_vector_s { 27 float tempo; 28 float amplitude; 29 float frequency; 30 float attack; 31 }; 32 33 34 struct envelope_result_s { 35 float tempo; 36 float attack; 37 }; 38 39 struct thread_result_s { 40 struct bl_song const * const song; 41 float result; 42 }; 43 44 struct thread_envelope_result_s { 45 struct bl_song const * const song; 46 struct envelope_result_s * results; 47 }; 48 49 struct bl_song { 50 float force; 51 struct force_vector_s force_vector; 52 int8_t* sample_array; 53 int channels; 54 int nSamples; 55 int sample_rate; 56 int bitrate; 57 int nb_bytes_per_sample; 58 int calm_or_loud; 59 int resampled; 60 uint64_t duration; 61 char* filename; 62 char* artist; 63 char* title; 64 char* album; 65 char* tracknumber; 66 char* genre; 67 }; 68 69 70 /** 71 * Run the analysis on the given song. 72 * 73 * @param[in] filename is the filename of the song to analyze. 74 * @param[out] current_song is the resulting `bl_song` structure after 75 * analysis. 76 * 77 * @return A value characterizing the song, whether calm, loud or 78 * error-specific. 79 */ 80 int bl_analyze(char const * const filename, 81 struct bl_song * current_song); 82 83 84 /** 85 * Compute the distance between two songs stored in audio files. 86 * 87 * @remark Distance is computed using a standard euclidian distance between 88 * force vectors. 89 * 90 * @param[in] filename1 is the path to the first song to compare. 91 * @param[in] filename2 is the path to the second song to compare. 92 * @param[out] song1 is the resulting `bl_song` structure for the first song, 93 * after analysis. 94 * @param[out] song2 is the resulting `bl_song` structure for the second song, 95 * after analysis. 96 * 97 * @return The distance between the two songs stored in audio files. 98 */ 99 float bl_distance_file( 100 char const * const filename1, 101 char const * const filename2, 102 struct bl_song * song1, 103 struct bl_song * song2); 104 105 /** 106 * Compute the distance between two songs. 107 * 108 * @remark Distance is computed using a standard euclidian distance between 109 * force vectors. 110 * 111 * @param[in] v_song1 is the first song's force vector to compare. 112 * @param[in] v_song2 is the second song's force vector to compare. 113 * 114 * @return The distance between the two songs. 115 */ 116 float bl_distance( 117 struct force_vector_s v_song1, 118 struct force_vector_s v_song2); 119 120 121 /** 122 * Compute the cosine similarity between two songs stored in audio files. 123 * 124 * @remark Returns a value between -1 and 1; -1 means songs are total opposites, 125 * 1 means that they are completely similar. 126 * 127 * @param[in] filename1 is the path to the first song to compare. 128 * @param[in] filename2 is the path to the second song to compare. 129 * @param[out] song1 is the resulting `bl_song` structure for the first song, 130 * after analysis. 131 * @param[out] song2 is the resulting `bl_song` structure for the second song, 132 * after analysis. 133 * 134 * @return The cosine similarity between the two songs stored in audio files. 135 */ 136 float bl_cosine_similarity_file( 137 char const * const filename1, 138 char const * const filename2, 139 struct bl_song * song1, 140 struct bl_song * song2); 141 142 143 /** 144 * Compute the cosine similarity between two songs. 145 * 146 * @param[in] v_song1 is the first song's force vector to compare. 147 * @param[in] v_song2 is the second song's force vector to compare. 148 * 149 * @return The cosine similarity between the two songs. 150 */ 151 float bl_cosine_similarity( 152 struct force_vector_s v_song1, 153 struct force_vector_s v_song2); 154 155 156 /********************** 157 * Specific analyzers * 158 **********************/ 159 160 /** 161 * Compute envelope-related characteristics: tempo and attack ratings. 162 * 163 * The tempo rating draws the envelope of the whole song, and then computes its 164 * DFT, obtaining peaks at the frequency of each dominant beat. The period of 165 * each dominant beat can then be deduced from the frequencies, hinting at the 166 * song's tempo. 167 * 168 * Warning: the tempo is not equal to the force of the song. As an example , a 169 * heavy metal track can have no steady beat at all, giving a very low tempo score 170 * while being very loud. 171 * 172 * The attack rating computes the difference between each value in the envelope 173 * and the next (its derivative). 174 * The final value is obtained by dividing the sum of the positive derivates by 175 * the number of samples, in order to avoid different results just because of 176 * the songs' length. 177 * As you have already guessed, a song with a lot of attacks also tends to wake 178 * humans up very quickly. 179 * 180 * @param[in] song the song to analyze. 181 * @param[out] result an `envelope_result_s` structure to handle the resulting 182 * ratings. 183 */ 184 void bl_envelope_sort(struct bl_song const * const song, 185 struct envelope_result_s * result); 186 187 188 /** 189 * Compute amplitude rating. 190 * 191 * The amplitude rating reprents the physical « force » of the song, that is, 192 * how much the speaker's membrane will move in order to create the sound. 193 * It is obtained by checking the shape of the histogram of the values of all 194 * the song's samples. The narrower the peak, the louder the song. 195 * 196 * @param[in] song the song to analyze. 197 * 198 * @return the amplitude rating. 199 */ 200 float bl_amplitude_sort(struct bl_song const * const song); 201 202 203 /** 204 * Compute frequency rating. 205 * 206 * The frequency rating is a ratio between high and low frequencies: a song 207 * with a lot of high-pitched sounds tends to wake humans up far more easily. 208 * This rating is obtained by performing a DFT over the sample array, and 209 * splitting the resulting array in 4 frequency bands: low, mid-low, mid, 210 * mid-high, and high. Using the value in dB for each band, the final formula 211 * corresponds to freq_result = high + mid-high + mid - (low + mid-low) 212 * 213 * @param[in] song the song to analyze. 214 * 215 * @return the frequency rating for this song. 216 */ 217 float bl_frequency_sort(struct bl_song const * const song); 218 219 220 /*********** 221 * Decoder * 222 ***********/ 223 224 /** 225 * Decode specified audio file. 226 * 227 * Decode the specified audio file with libAV and fill in the song structure. 228 * 229 * @param[in] filename name of the file to decode and load. 230 * @param[out] song the `bl_song` song structure to fill. 231 * 232 * @return `BL_OK` if everything went fine, `BL_UNEXPECTED` otherwise. 233 */ 234 int bl_audio_decode(char const * const filename, 235 struct bl_song * const song); 236 237 238 /*********** 239 * Helpers * 240 * *********/ 241 242 /** 243 * Free the dynamically allocated memory to store song data. 244 * 245 * @param song a `bl_song` struct representing the song to free. 246 */ 247 void bl_free_song(struct bl_song * const song); 248 249 /** 250 * Display the current version number of bliss 251 * 252 * @return The current version, as written in `BL_VERSION` 253 */ 254 float bl_version(void); 255 256 /** 257 * Initialize a bl_song by settings pointers to NULL so that it can be freed even 258 * if an analysis couldn't be performed. 259 * 260 * @param song a `bl_song` struct representing the song to initialize 261 */ 262 void bl_initialize_song(struct bl_song * const song); 263 264 /** 265 * Compute the mean of a double array. 266 * 267 * @param[in] sample_array an array of samples 268 * @param[in] nSamples the array's size (in double) 269 */ 270 int bl_mean(int16_t *sample_array, int nSamples); 271 272 /** 273 * Compute the variance of a double array. 274 * 275 * @param[in] sample_array an array of samples 276 * @param[in] nSamples the array's size (in double) 277 */ 278 int bl_variance(int16_t *sample_array, int nSamples, int mean); 279 280 /** 281 * A rectangular filter that smoothes an array of samples 282 * 283 * @param[in] sample_array_in an array of samples 284 * @param[in] nSamples the array's size (in double) 285 * @param[in] smooth_width smooth width, e.g. the m adjacents points to average 286 * @param[out] sample_array_out the filtered sample array 287 * 288 */ 289 void bl_rectangular_filter(double *sample_array_out, double * sample_array_in, 290 int nSamples, int smooth_width); 291 #endif // BL_BLISS_H_ 292