Aggiunta basilare gestione delle tracce audio

Leonardo [2010-05-14 15:18]
Aggiunta basilare gestione delle tracce audio
Filename
main.c
simple_audio.c
simple_audio.h
diff --git a/main.c b/main.c
index fb992fb..7c5705b 100644
--- a/main.c
+++ b/main.c
@@ -13,14 +13,33 @@ int main(int argc, char** argv) {
   sine.fs->sin_values[0] = 1.0;
   sine.fs->a_0 = 0;

-  sample* ss = sa_note(sine, "A3", 44100);
-  sa_write_samples("prova.cdr", ss, 44100);
+  sa_instrument organ;
+  int j;
+  organ.fs = (sa_fourier_series*) malloc(sizeof(sa_fourier_series));
+  organ.fs->cos_len = 0;
+  organ.fs->sin_len = 100;
+  organ.fs->sin_values = malloc(sizeof(double) * 100);
+  organ.fs->a_0 = 0;
+  for(j = 0; j < 100; j++) {
+    if(j % 2 == 1)
+      organ.fs->sin_values[j] = 0;
+    else
+      organ.fs->sin_values[j] = 1.0 / (j+1) / 3.1415926;
+  }
+
+  sa_track* track = sa_track_new(2);
+
+
+  sample* ss = sa_note(organ, "A3", 44100);
+  sa_track_append(track, ss, 44100, 0);
+  sa_track_append(track, ss, 44100, 1);
+
+  ss = sa_note(organ, "B3", 44100);
+  sa_track_append(track, ss, 44100, 0);
+  sa_track_append(track, ss, 44100, 1);
+
+  sa_track_write(track, "prova.cdr");

-  sample s = 1, t;
-  t = sa_swap_bytes(s);
-  printf("%d, %d\n", s,t);
-  printf("sa_is_little_endian() = %d\n", sa_is_little_endian());
-  printf("sa_is_big_endian() = %d\n", sa_is_big_endian());
   return 0;
 }

diff --git a/simple_audio.c b/simple_audio.c
index 0841f36..3555d51 100644
--- a/simple_audio.c
+++ b/simple_audio.c
@@ -5,6 +5,77 @@
 #include <string.h>
 #define PID 6.28318

+sa_track* sa_track_new(int n) {
+  sa_track* t = malloc(sizeof(sa_track));
+  int i;
+  t->channels = n;
+  t->len = malloc(sizeof(int) * n);
+  t->data = malloc(sizeof(sample*) * n);
+  for (i = 0; i < n; i++) {
+    t->data[i] = NULL;
+    t->len[i] = 0;
+  }
+  return t;
+}
+
+int sa_track_free(sa_track* t) {
+  int i;
+  for(i=0; i < t->channels; i++) {
+    free(t->data[i]);
+  }
+  free(t->len);
+  free(t->data);
+  return 0;
+}
+
+int sa_track_append(sa_track* t, sample* s, int n, int channel) {
+  if(channel > t->channels) {
+    fprintf(stderr, "Trying to channel %d, but track has on ly %d channels\n", channel, t->channels);
+    exit(EXIT_FAILURE);
+  }
+  // Allargo lo spazio
+
+  if(!t->data[channel]) { t->data[channel] = (sample*) malloc(n * sizeof(sample)); }
+  else {
+    t->data[channel] = (sample*) realloc(t->data[channel], (t->len[channel] + n)* sizeof(sample));
+  }
+  memcpy(t->data[channel] + t->len[channel], s, n * sizeof(sample));
+  t->len[channel] = t->len[channel] + n;
+
+  return 0;
+}
+
+int sa_track_write(sa_track* t, char* filename) {
+
+  FILE* handle;
+  int counter, j;
+  sample buf;
+
+  if( (handle = fopen(filename, "w")) == NULL )
+    {
+      fprintf(stderr, "Impossibile aprire il file %s\n", filename);
+      exit(EXIT_FAILURE);
+    }
+
+  for(j = 1; j < t->channels; j++) {
+    if(t->len[j] != t->len[0]) {
+      fprintf(stderr, "Tutte le tracce devono avere lo stesso numero di canali!\n");
+    }
+  };
+
+  for(counter = 0; counter < t->len[0]; counter ++) {
+    for (j = 0; j < t->channels; j++) {
+      buf = t->data[j][counter];
+      if(sa_is_little_endian()) { buf = sa_swap_bytes(buf); }
+      fwrite(&buf, sizeof(buf), 1, handle);
+    }
+  }
+
+  fclose (handle);
+  return EXIT_SUCCESS;
+
+}
+
 sample sa_note_sample(sa_instrument* instrument, double frequency, double time) {

   // Calcolo il risultato della serie di Fourier al tempo time
@@ -23,7 +94,6 @@ sample sa_note_sample(sa_instrument* instrument, double frequency, double time)

 sample sa_double_to_sample(double s) {
   short int t = (short int) (32768 * s);
-  printf("%d\n", t);
   sample ret;
   memcpy(&ret, &t, sizeof(sample));
   return ret;
@@ -35,23 +105,23 @@ double sa_parse_note(char* note) {

   // Prima scala
   base = 440.0;
-  if (strcmp(note, "A2")) { return 440.0; }
-  if (strcmp(note, "B2")) { return base * pow(r2, 2); }
-  if (strcmp(note, "C3")) { return base * pow(r2, 3); }
-  if (strcmp(note, "D3")) { return base * pow(r2, 5); }
-  if (strcmp(note, "E3")) { return base * pow(r2, 7); }
-  if (strcmp(note, "F3")) { return base * pow(r2, 8); }
-  if (strcmp(note, "G3")) { return base * pow(r2,10); }
+  if (strcmp(note, "A2") == 0) { return 440.0; }
+  if (strcmp(note, "B2") == 0) { return base * pow(r2, 2); }
+  if (strcmp(note, "C3") == 0) { return base * pow(r2, 3); }
+  if (strcmp(note, "D3") == 0) { return base * pow(r2, 5); }
+  if (strcmp(note, "E3") == 0) { return base * pow(r2, 7); }
+  if (strcmp(note, "F3") == 0) { return base * pow(r2, 8); }
+  if (strcmp(note, "G3") == 0) { return base * pow(r2,10); }

   // Seconda scala
   base = 880.0;
-  if (strcmp(note, "A3")) { return base;              }
-  if (strcmp(note, "B3")) { return base * pow(r2, 2); }
-  if (strcmp(note, "C4")) { return base * pow(r2, 3); }
-  if (strcmp(note, "D4")) { return base * pow(r2, 5); }
-  if (strcmp(note, "E4")) { return base * pow(r2, 7); }
-  if (strcmp(note, "F4")) { return base * pow(r2, 8); }
-  if (strcmp(note, "G4")) { return base * pow(r2,10); }
+  if (strcmp(note, "A3") == 0) { return base;              }
+  if (strcmp(note, "B3") == 0) { return base * pow(r2, 2); }
+  if (strcmp(note, "C4") == 0) { return base * pow(r2, 3); }
+  if (strcmp(note, "D4") == 0) { return base * pow(r2, 5); }
+  if (strcmp(note, "E4") == 0) { return base * pow(r2, 7); }
+  if (strcmp(note, "F4") == 0) { return base * pow(r2, 8); }
+  if (strcmp(note, "G4") == 0) { return base * pow(r2,10); }

   return base;
 }
@@ -59,6 +129,7 @@ double sa_parse_note(char* note) {
 sample* sa_note(sa_instrument instrument, char* note, int len) {

   double frequency = sa_parse_note (note);
+  printf("Mapped %s to %lf Hz\n", note, frequency);
   int i;
   sample* s = (sample*) malloc(len * sizeof(sample));
   for(i = 0; i < len; i++) {
@@ -79,25 +150,6 @@ sample sa_swap_bytes(sample s) {
 }


-int sa_write_samples(char* filename, sample* samples, int len) {
-  FILE* handle;
-  if( (handle = fopen(filename, "w")) == NULL )
-    {
-      fprintf(stderr, "Impossibile aprire il file %s\n", filename);
-      exit(EXIT_FAILURE);
-    }
-
-  int counter;
-  sample buf;
-  for(counter = 0; counter < len; counter ++) {
-    buf = samples[counter];
-    if(sa_is_little_endian()) { buf = sa_swap_bytes(buf); }
-    fwrite(&buf, sizeof(buf), 1, handle);
-    fwrite(&buf, sizeof(buf), 1, handle);
-  }
-  fclose (handle);
-  return EXIT_SUCCESS;
-}

 int sa_is_little_endian() {
   unsigned char endian[] = { 1, 0};
diff --git a/simple_audio.h b/simple_audio.h
index 6c4ab07..83a7b15 100644
--- a/simple_audio.h
+++ b/simple_audio.h
@@ -46,6 +46,24 @@ typedef union {
   unsigned char bytes[2];
 } sample_b;

+
+// Traccia audio
+typedef struct {
+  int channels;
+  sample** data;
+  int* len;
+} sa_track;
+
+
+// Crea una traccia vuota con n canali
+sa_track* sa_track_new(int n);
+
+// Elimina una traccia e tutto il suo contenuto
+int sa_track_free(sa_track* t);
+
+// Aggiunge dati ad una traccia
+int sa_track_append(sa_track* t, sample* s, int len, int channel);
+
 // Genera un singolo sample dello strumento prescelto dopo
 // un certo tempo
 sample sa_note_sample(sa_instrument* instrument, double frequency, double time);
@@ -60,8 +78,8 @@ sample sa_double_to_sample(double);
 // nota scelta
 sample* sa_note(sa_instrument instrument, char* note, int len);

-// Scrive delle sample sul file prescelto
-int sa_write_samples(char* filename, sample* samples, int len);
+// Scrive la traccia su file
+int sa_track_write(sa_track* t, char* filename);

 // Determina se il computer sta usando la convenzione little
 // endian o  big endian
ViewGit