ReMAS  1.5
Real-time Musical Accompaniment System
ServerCPU.c
Go to the documentation of this file.
1  /**************************************************************************
2  * Copyright (C) 2017 by "Information Retrieval and Parallel Computing" *
3  * group (University of Oviedo, Spain), "Interdisciplinary Computation *
4  * and Communication" group (Polytechnic University of Valencia, Spain) *
5  * and "Signal Processing and Telecommunication Systems Research" group *
6  * (University of Jaen, Spain) *
7  * Contact: remaspack@gmail.com *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the *
21  * Free Software Foundation, Inc., *
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23  **************************************************************************
24 */
35 /* This include the first. Only needed when function for waiting some milliseconds is used */
36 #include "TimeFunctions.h"
37 
38 #include "CPUFunctions.h"
39 #include "FileFunctions.h"
40 #include "SoundFunctions.h"
41 #include "TempoFunctions.h"
42 #include "NetFunctions.h"
43 
44 #ifdef CAUDIO
45  #include "MacOSSoundFunctions.h"
46  #pragma mark main function
47 #endif
48 
55 int main(int argc , char *argv[])
56 {
57  /* Using only by DTW */
58  int
59  pos_min,
60  DTWWhere, DTWSize,
61  DTWSizePlusPad;
62 
63  MyType
64  *pD = NULL,
65  Costs[T_COSTS];
66 
67  /* Using only by FFT */
68  MyFFTCPUType
69  plan;
70 
71  MyType
72  *X_fft =NULL,
73  *Out_fft=NULL,
74  *Mod_fft=NULL;
75 
76  int
77  kmax_fft[N_MIDI],
78  kmin_fft[N_MIDI];
79 
80  /* Using only by HMM (silence detection) */
81  MyType
82  prob_silen = (MyType)0.75,
83  prob_audio = (MyType)0.25;
84 
85  bool
86  Silence=true;
87 
88  /* Using by other preprocessing steps */
89  MyType
90  *norms = NULL,
91  *s_fk = NULL,
92  *v_SxD = NULL,
93  *v_cfreq = NULL,
94  *v_hanning = NULL,
95  *v_dxState = NULL,
96  *tauxi = NULL,
97  *ts_fk = NULL,
98  BETA=(MyType)1.5;
99 
100  int
101  *states_time_i=NULL,
102  *states_time_e=NULL,
103  *states_seq =NULL,
104  *states_corr =NULL,
105  *I_SxD =NULL;
106 
107  short
108  *frame=NULL;
109 
110  DTWconst Param;
111  DTWfiles NameFiles;
112  WAVHeader WavHeader;
113 
114  /* For Linux when audio comes from microphone input device */
115  #ifdef ALSA
116  snd_pcm_t *SoundHandle=NULL;
117  snd_pcm_uframes_t SoundBufferSize;
118  #endif
119 
120  /* For MacOS when audio comes from microphone input device */
121  #ifdef CAUDIO
122  RecorderStruct recorder = {0};
123  AudioQueueRef queue = {0};
124  #endif
125 
126  /* Using by OSC for messages. Limited to MaxOSC (see defines.h) clients */
127  #ifdef OSC
128  lo_address DirOSC[MaxOSC];
129  #endif
130 
131  /* For TEMPO */
132  //STempo TEMPO={.MidiFrame=0, .RealFrame=0, .NextFrame=0, .PrevState=0, .SynthSpeed=1.0, .SoloSpeed=.0, .SynthTime=.0};
133 
134  STempoRL TEMPORL={.NextFrame=0, .PrevState=0, .AudioTimeAP[0]=0, .ScoreTimeAP[0]=0, .SynthSpeed=1.0,
135  .SoloSpeed=1.0, .SynthTime=0.0, .numap=1, .matched=1};
136  int *preload=NULL;
137 
138  /* For Docker and AppImage usage */
139  bool UseOSC=false, UseMic=false;
140 
141  /* For time under OpenMP */
142  #ifdef OMP
143  double time=0.0;
144  #endif
145 
146  /* General & others variables */
147  int i, j, NumTramas=0;
148  FILE *fp = NULL;
149 
150  /* Reading global paramentes */
151  switch(argc) {
152  case 3: /* Regular use */
153  #ifdef SIMPLE
154  BETA=strtof(argv[1], NULL);
155  #else
156  BETA=strtod(argv[1], NULL);
157  #endif
158  #ifdef OSC
159  UseOSC=true;
160  #endif
161  #if defined(ALSA) || defined(CAUDIO)
162  UseMic=true;
163  #endif
164  break;
165  case 5: /* For Docker or AppImagen */
166  #ifdef SIMPLE
167  BETA=strtof(argv[1], NULL);
168  #else
169  BETA=strtod(argv[1], NULL);
170  #endif
171  UseOSC=atoi(argv[3]);
172  UseMic=atoi(argv[4]);
173  break;
174  default:
175  printf("General usage: %s <BETA> <configuration file>\n", argv[0]);
176  printf(" Example: %s 1.5 parametes.dat\n\n", argv[0]);
177  printf("Docker usage: %s <BETA> <configuration file> <OSC yes|no [1|0]> <Microphone yes|no [1|0]>\n", argv[0]);
178  printf(" Example: %s 1.5 parametes.dat 1 1\n\n", argv[0]);
179  return -1;
180  }
181 
182  /* Reading general information and file names */
183  CHECKERR(ReadParameters(&Param, &NameFiles, argv[2]));
184 
185  /* Allocating memory and reading some structures */
186  CHECKERR(AllocDataCPU(&v_hanning, &states_time_i, &states_time_e, &states_seq, &states_corr, &I_SxD, &DTWSize, TAMTRAMA, Param.N_STATES, NameFiles));
187 
188  /* Allocating memory for and setting some DTW constants */
189  DTWSizePlusPad =(DTWSize + N_COSTS) * (N_COSTS + 1);
190  CHECKERR(AllocDTWCPU(&pD, &v_SxD, DTWSize, DTWSizePlusPad, 1));
191 
192  /* Allocating memory for s_fk and auxiliar structures when Beta !=0.0 and !=1.0 */
193  CHECKERR(AllocS_fkCPU(&s_fk, &tauxi, &ts_fk, BETA, N_MIDI_PAD, Param.N_BASES, NameFiles));
194 
195  /* Allocating memory for FFT memory and reading data */
196  CHECKERR(AllocFFTCPU(&plan, &X_fft, &Out_fft, &Mod_fft, kmin_fft, kmax_fft, N_FFT, NameFiles));
197 
198  /* Allocating memory for the rest of general structures */
199  CHECKERR(AllocAuxiCPU(&norms, &frame, &v_cfreq, &v_dxState, Param.N_BASES, TAMTRAMA, N_MIDI));
200 
201  /* Initializing vector of costs */
202  Costs[0] = 1.0; // Distance to (1,1)
203  Costs[1] = 1.0; // Distance to (1,2)
204  Costs[2] = 1.0; // Distance to (1,3)
205  Costs[3] = 1.0; // Distance to (1,4)
206  Costs[4] = 2.0; // Distance to (2,1)
207  Costs[5] = 3.0; // Distance to (3,1)
208  Costs[6] = 4.0; // Distance to (4,1)
209 
210  /* For TEMPO */
211  CHECKNULL(preload=(int *)calloc(DTWSize, sizeof(int)));
212  j=0;
213  for (i=0; i<DTWSize; i++)
214  {
215  if (i > states_time_e[j]) j++;
216  preload[i]=j;
217  }
218 
219  /* If OSC UPD is available */
220  #ifdef OSC
221  if (UseOSC)
222  for (i=0; i<Param.NCliOSC; i++)
223  {
224  /* Declare an OSC destination, given IP address and port number, using UDP */
225  CHECKERR(lo_address_errno(DirOSC[i]=lo_address_new(Param.HostIP[i], Param.HostPort[i])));
226  #ifdef TALK
227  printf("IPV4 %s, Port %s\n", Param.HostIP[i], Param.HostPort[i]);
228  #endif
229  }
230  #endif
231 
232  /* Configure microphone input device if ALSA (Linux) or Core Audio (MacOS) is used */
233  #ifdef ALSA
234  if (UseMic)
235  {
236  SoundBufferSize=SetMicParams(&SoundHandle, Param);
237  if (SoundBufferSize <=0) CHECKERR(ErrAlsaHw);
238 
239  #ifdef DUMP
240  CHECKNULL(fp=fopen("FramesMicRecorded.pcm", "w"));
241  #endif
242  NumTramas = (Param.Time_MIC * AlsaRate) / TAMMUESTRA;
243  }else{
244  CHECKNULL(fp=fopen(NameFiles.file_frame, "rb"));
245 
246  CHECKERR(Read_WAVHeader(&WavHeader, fp));
247  NumTramas = (WavHeader.num_samples - TAMTRAMA) / TAMMUESTRA;
248  }
249  #else
250  #ifdef CAUDIO
251  if (UseMic)
252  {
253  ConfigureAndAllocAudioQueues(&recorder, &queue);
254  recorder.running = TRUE;
255  CheckError(AudioQueueStart(queue, NULL), "AudioQueueStart failed");
256 
257  #ifdef DUMP
258  CHECKNULL(fp=fopen("FramesMicRecorded.pcm", "wb"));
259  #endif
260  NumTramas = (Param.Time_MIC * AQRate) / TAMMUESTRA;
261  }else{
262  CHECKNULL(fp=fopen(NameFiles.file_frame, "rb"));
263 
264  CHECKERR(Read_WAVHeader(&WavHeader, fp));
265  NumTramas = (WavHeader.num_samples - TAMTRAMA) / TAMMUESTRA;
266  }
267  #else
268  CHECKNULL(fp=fopen(NameFiles.file_frame, "rb"));
269 
270  CHECKERR(Read_WAVHeader(&WavHeader, fp));
271  NumTramas = (WavHeader.num_samples - TAMTRAMA) / TAMMUESTRA;
272  #endif
273  #endif
274 
275  /* Compute s_fk norms */
276  ComputeNorms(norms, ts_fk, s_fk, N_MIDI, Param.N_BASES, BETA);
277 
278  /* Fills the buffer */
279  #ifdef ALSA
280  if (UseMic)
281  CHECKERR(ReadAlsaCPU1st(frame, SoundHandle, fp));
282  else
283  CHECKERR(ReadWavCPU1st(frame, fp));
284  #else
285  #ifdef CAUDIO
286  if (UseMic)
287  CHECKERR(ReadAudioQueue1st(frame, &recorder, fp));
288  else
289  CHECKERR(ReadWavCPU1st(frame, fp));
290  #else
291  CHECKERR(ReadWavCPU1st(frame, fp));
292  #endif
293  #endif
294 
295  #ifdef TALK
296  printf("Listening ...\n");
297  #endif
298 
299  /* Procedure for silence/white noise detection */
300  while (Silence)
301  {
302  #ifdef ALSA
303  if (UseMic)
304  CHECKERR(ReadAlsaCPU(frame, SoundHandle, fp));
305  else
306  CHECKERR(ReadWavCPU(frame, fp));
307  #else
308  #ifdef CAUDIO
309  if (UseMic)
310  CHECKERR(ReadAudioQueue(frame, &recorder, fp));
311  else
312  CHECKERR(ReadWavCPU(frame, fp));
313  #else
314  CHECKERR(ReadWavCPU(frame, fp));
315  #endif
316  #endif
317  NumTramas--;
318 
319  ApplyWindow(X_fft, frame, v_hanning, TAMTRAMA, N_FFT);
320  FFT (v_cfreq, kmin_fft, kmax_fft, X_fft, Mod_fft, Out_fft, plan, N_FFT, N_MIDI);
321  BetaNorm (v_cfreq, N_MIDI, BETA);
322  ComputeDist(v_cfreq, v_dxState, tauxi, norms, s_fk, ts_fk, BETA, Param.N_BASES, N_MIDI);
323  Silence = DetectSilence((v_dxState[1]-v_dxState[0]), &prob_silen, &prob_audio);
324  }
325 
326  /* Start OSC */
327  #ifdef OSC
328  if (UseOSC) for (i=0; i<Param.NCliOSC; i++) { CHECKERR(SendPlay(DirOSC[i])); CHECKERR(SendTempo(DirOSC[i], 110)); }
329  #endif
330 
331  #ifdef OMP
332  time=omp_get_wtime();
333  #endif
334 
335  /* start the system */
336  for(i=1; i<=NumTramas; i++)
337  {
338  ApplyWindow(X_fft, frame, v_hanning, TAMTRAMA, N_FFT);
339  FFT (v_cfreq, kmin_fft, kmax_fft, X_fft, Mod_fft, Out_fft, plan, N_FFT, N_MIDI);
340  ComputeDist(v_cfreq, v_dxState, tauxi, norms, s_fk, ts_fk, BETA, Param.N_BASES, N_MIDI);
341  ApplyDist (v_dxState, v_SxD, I_SxD, DTWSize, Param.ALPHA);
342 
343  // DTW
344  DTWWhere=(i % TBLOCK) * (N_COSTS + DTWSize) + N_COSTS;
345  pos_min=DTWProc(v_SxD, Costs, pD, i, DTWWhere, DTWSize);
346 
347  #ifdef TALK
348  printf("Frame %d, PosMin %d\n", i, pos_min);
349  #endif
350 
351  /* Is it necessary to recalculate the tempo? (sec 2.4.1) */
352  #ifdef OSC
353  if (UseOSC)
354  {
355  //CHECKERR(ComputeTempoOSC(&TEMPO, i, pos_min, preload[pos_min], states_corr, DirOSC, Param.NCliOSC, Param.N_STATES));
356  CHECKERR(ComputeTempoOSCRL(&TEMPORL, i, pos_min, preload[pos_min], states_corr, DirOSC, Param.NCliOSC));
357  }
358  else
359  {
360  //ComputeTempo(&TEMPO, i, pos_min, preload[pos_min], states_corr, Param.N_STATES);
361  ComputeTempoRL(&TEMPORL, i, pos_min, preload[pos_min], states_corr);
362  }
363  #else
364  //ComputeTempo(&TEMPO, i, pos_min, preload[pos_min], states_corr, Param.N_STATES);
365  ComputeTempoRL(&TEMPORL, i, pos_min, preload[pos_min], states_corr);
366  #endif
367 
368  #if !defined(ALSA) && !defined(CAUDIO)
369  /* waiting some milliseconds: simulating within the WAV file the audio delay */
370  //CHECKERR(msleep(10));
371  #endif
372 
373  // Read new data
374  #ifdef ALSA
375  if (UseMic)
376  CHECKERR(ReadAlsaCPU(frame, SoundHandle, fp));
377  else
378  CHECKERR(ReadWavCPU(frame, fp));
379  #else
380  #ifdef CAUDIO
381  if (UseMic)
382  CHECKERR(ReadAudioQueue(frame, &recorder, fp));
383  else
384  CHECKERR(ReadWavCPU(frame, fp));
385  #else
386  CHECKERR(ReadWavCPU(frame, fp));
387  #endif
388  #endif
389  }
390 
391  #ifdef OMP
392  time=omp_get_wtime() - time;
393  printf("%f sec.\n", time);
394  #endif
395 
396  /* Leave MS on tempo 1, stop and frees*/
397  #ifdef OSC
398  if (UseOSC)
399  for (i=0; i<Param.NCliOSC; i++) { CHECKERR(SendTempo(DirOSC[i], 100)); CHECKERR(SendPlay(DirOSC[i])); }
400  #endif
401 
402  /* Close files and free sound device if used */
403  FreeFiles(&NameFiles);
404  #ifdef ALSA
405  if (UseMic)
406  {
407  #ifdef DUMP
408  fclose(fp);
409  #endif
410  CHECKERR(snd_pcm_close(SoundHandle));
411  } else { fclose(fp); }
412  #else
413  #ifdef CAUDIO
414  if (UseMic)
415  {
416  #ifdef DUMP
417  fclose(fp);
418  #endif
419  recorder.running = FALSE;
420  CheckError(AudioQueueStop(queue, TRUE), "AudioQueueStop failed");
421  AudioQueueDispose(queue, TRUE);
422  } else { fclose(fp); }
423  #else
424  fclose(fp);
425  #endif
426  #endif
427 
428  /* frees in general. Is it necessary ? Not really but it is our habit */
429  if (!(BETA>=(MyType)0.0 && BETA<=(MyType)0.0) && !(BETA>=(MyType)1.0 && BETA<=(MyType)1.0)) {
430  free(tauxi);
431  free(ts_fk);
432  }
433  free(I_SxD);
434  free(Mod_fft);
435  free(norms);
436  free(pD);
437  free(s_fk);
438  free(preload);
439  free(states_corr);
440  free(states_seq);
441  free(states_time_i);
442  free(states_time_e);
443  free(frame);
444  free(v_cfreq);
445  free(v_dxState);
446  free(v_hanning);
447  free(v_SxD);
448  free(X_fft);
449  #ifdef SIMPLE
450  fftwf_free(Out_fft);
451  fftwf_destroy_plan(plan);
452  #ifdef PARFFTW
453  fftwf_cleanup_threads();
454  #endif
455  #else
456  fftw_free(Out_fft);
457  fftw_destroy_plan(plan);
458  #ifdef PARFFTW
459  fftw_cleanup_threads();
460  #endif
461  #endif
462 
463  return OK;
464 }
int NCliOSC
Definition: defines.h:199
Struct for store the name of input/verificaton files. Each composition needs a file with values for ...
Definition: defines.h:228
Struct for Compute tempos.
Definition: defines.h:292
File with TEMPO and auxiliar functions using by ReMAS, both CPU and GPU.
File with sound (using ALSA) and auxiliar functions using by ReMAS, both CPU and GPU.
void ApplyDist(const MyType *v_dxState, MyType *v_SxD, const int *I_SxD, const int size, const MyType ALPHA)
ApplyDist applies distortion.
Definition: CPUFunctions.c:550
int AllocS_fkCPU(MyType **s_fk, MyType **tauxi, MyType **ts_fk, const MyType BETA, const int nmidi, const int nbases, DTWfiles NameFiles)
AllocS_fkCPU Allocates memory for S_fk vector, read its data from file and initializes other auxiliar...
Definition: CPUFunctions.c:231
int ReadWavCPU1st(short *frame, FILE *fp)
ReadWavCPU1st reads first audio (frame) from WAV file when ARM is used.
Definition: CPUFunctions.c:742
int N_BASES
Definition: defines.h:192
void BetaNorm(MyType *v_cfreq, const int nmidi, MyType BETA)
BetaNorm normalizes v_cfreq vector to have beta-norm 1.
Definition: CPUFunctions.c:817
int Read_WAVHeader(WAVHeader *, FILE *)
Read_WAVHeader reads header of a WAVE file, checks its compability and fill Header struct...
File with functions used by ReMAS, both CPU and GPU, for management communications.
int DTWProc(const MyType *Sequence, const MyType *Costs, MyType *__restrict pD, const int NSeq, const int Where, const int NST)
DTWProc performs the Online-DTW process for the current frame.
Definition: CPUFunctions.c:485
File with functions used by ReMAS, both CPU and GPU, for management the time.
Header file with auxiliar functions using by ReMAS, both CPU and GPU.
char HostPort[MaxOSC][5]
Definition: defines.h:201
void FreeFiles(DTWfiles *NameFiles)
FreeFiles frees the reserved memory of a struct.
Struct for WAVE file header. WAV files definitions. Note that we only work with 1 channel...
Definition: defines.h:251
Header file for using ReMAS with CPU, both x86_64 and ARM.
int AllocDTWCPU(MyType **pV, MyType **v_SxD, const int DTWSize, const int DTWSizePlusPad, const int startin)
AllocDTWCPU Allocates memory for DTW vectors and initializes them.
Definition: CPUFunctions.c:270
int Time_MIC
Definition: defines.h:198
void FFT(MyType *v_cfreq, const int *kmin, const int *kmax, MyType *X_fft, MyType *Mod_fft, MyType *Out_fft, MyFFTCPUType plan, const int nfft, const int nmidi)
FFT computes FFT and updates v_cfreq vector.
Definition: CPUFunctions.c:356
char HostIP[MaxOSC][16]
Definition: defines.h:200
int AllocFFTCPU(MyFFTCPUType *plan, MyType **X_fft, MyType **Out_fft, MyType **Mod_fft, int *kmin_fft, int *kmax_fft, const int nfft, DTWfiles NameFiles)
AllocFFTCPU Allocates memory for FFT vector and reads some fft information from files.
Definition: CPUFunctions.c:177
void ComputeNorms(MyType *norms, MyType *ts_fk, const MyType *s_fk, const int nmidi, const int nbases, const MyType beta)
ComputeNorms fills norms vector.
Definition: CPUFunctions.c:73
void ComputeTempoRL(STempoRL *, int, int, int, int *)
ComputeTempoRL calculates tempo and controls synthesizer speed using linear regression.
int main(int argc, char *argv[])
main is the entry point to ReMAS, classical C main program.
Definition: ServerCPU.c:55
int N_STATES
Definition: defines.h:193
long num_samples
Definition: defines.h:266
bool DetectSilence(MyType, MyType *, MyType *)
DetectSilence checks whether audio (frame) is silence or audio.
int ReadParameters(DTWconst *Param, DTWfiles *NameFiles, const char *filename)
ReadParameters reads ReMAS global parameters from file.
Definition: FileFunctions.c:48
int ReadWavCPU(short *frame, FILE *fp)
ReadWavCPU reads current audio (frame) from WAV file when ARM is used.
Definition: CPUFunctions.c:756
Struct for store global information of the problem. Each composition needs a file with values for th...
Definition: defines.h:190
int AllocDataCPU(MyType **v_hanning, int **states_time_i, int **states_time_e, int **states_seq, int **states_corr, int **I_SxD, int *DTWSize, const int tamframe, const int nstates, DTWfiles NameFiles)
AllocDataCPU creates and initializes some structures reading info from files.
Definition: CPUFunctions.c:310
char * file_frame
Definition: defines.h:232
File with sound (using CoreAudio) to access to default input audio, both CPU and GPU.
void ApplyWindow(MyType *__restrict X_fft, const short *frame, const MyType *v_hanning, const int framesize, const int xfftsize)
ApplyWindow applies hanning window to the current frame and store the result en vector X_fft...
Definition: CPUFunctions.c:48
int AllocAuxiCPU(MyType **norms, short **frame, MyType **v_cfreq, MyType **v_dxState, const int nbases, const int tamframe, const int nmidi)
AllocAuxiCPU Memory reservation for norms, frame, v_cfreq and v_dxState vectors.
Definition: CPUFunctions.c:152
void ComputeDist(const MyType *v_cfreq, MyType *__restrict v_dxStates, MyType *tauxi, const MyType *norms, const MyType *s_fk, const MyType *ts_fk, const MyType BETA, const int nbases, const int nmidi)
ComputeDist computes distortion.
Definition: CPUFunctions.c:600
MyType ALPHA
Definition: defines.h:195