static gboolean tone_play(const gchar *filename, VFSFile *file) { GArray *frequencies; gfloat data[BUF_SAMPLES]; gsize i; gboolean error = FALSE; struct { gdouble wd; guint period, t; } *tone = NULL; frequencies = tone_filename_parse(filename); if (frequencies == NULL) return FALSE; if (aud_input_open_audio(FMT_FLOAT, OUTPUT_FREQ, 1) == 0) { error = TRUE; goto error_exit; } aud_input_set_bitrate(16 * OUTPUT_FREQ); tone = g_malloc(frequencies->len * sizeof(*tone)); for (i = 0; i < frequencies->len; i++) { gdouble f = g_array_index(frequencies, gdouble, i); tone[i].wd = 2 * PI * f / OUTPUT_FREQ; tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * (OUTPUT_FREQ / f); tone[i].t = 0; } while (!aud_input_check_stop()) { for (i = 0; i < BUF_SAMPLES; i++) { gsize j; double sum_sines; for (sum_sines = 0, j = 0; j < frequencies->len; j++) { sum_sines += sin(tone[j].wd * tone[j].t); if (tone[j].t > tone[j].period) tone[j].t -= tone[j].period; tone[j].t++; } /* dithering can cause a little bit of clipping */ data[i] = (sum_sines * 0.999 / (gdouble) frequencies->len); } aud_input_write_audio(data, BUF_BYTES); } error_exit: g_array_free(frequencies, TRUE); g_free(tone); return !error; }
static gchar *tone_title(const gchar * filename) { GArray *freqs; gchar *title; gsize i; freqs = tone_filename_parse(filename); if (freqs == NULL) return NULL; title = g_strdup_printf(_("%s %.1f Hz"), _("Tone Generator: "), g_array_index(freqs, double, 0)); for (i = 1; i < freqs->len; i++) { gchar *old_title = title; title = g_strdup_printf("%s;%.1f Hz", old_title, g_array_index(freqs, double, i)); g_free(old_title); } g_array_free(freqs, TRUE); return title; }
static gboolean tone_play(InputPlayback *playback, const gchar *filename, VFSFile *file, gint start_time, gint stop_time, gboolean pause) { GArray *frequencies; gfloat data[BUF_SAMPLES]; gsize i; gboolean error = FALSE; struct { gdouble wd; guint period, t; } *tone = NULL; frequencies = tone_filename_parse(filename); if (frequencies == NULL) return FALSE; if (playback->output->open_audio(FMT_FLOAT, OUTPUT_FREQ, 1) == 0) { error = TRUE; goto error_exit; } if (pause) playback->output->pause(TRUE); playback->set_params(playback, 16 * OUTPUT_FREQ, OUTPUT_FREQ, 1); tone = g_malloc(frequencies->len * sizeof(*tone)); for (i = 0; i < frequencies->len; i++) { gdouble f = g_array_index(frequencies, gdouble, i); tone[i].wd = 2 * PI * f / OUTPUT_FREQ; tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * (OUTPUT_FREQ / f); tone[i].t = 0; } stop_flag = FALSE; playback->set_pb_ready(playback); while (!stop_flag) { for (i = 0; i < BUF_SAMPLES; i++) { gsize j; double sum_sines; for (sum_sines = 0, j = 0; j < frequencies->len; j++) { sum_sines += sin(tone[j].wd * tone[j].t); if (tone[j].t > tone[j].period) tone[j].t -= tone[j].period; tone[j].t++; } /* dithering can cause a little bit of clipping */ data[i] = (sum_sines * 0.999 / (gdouble) frequencies->len); } if (!stop_flag) playback->output->write_audio(data, BUF_BYTES); } error_exit: g_array_free(frequencies, TRUE); g_free(tone); playback->output->close_audio(); stop_flag = TRUE; return !error; }