/* Processes the audio segment into discrete frequency bins with an FFT */ static void *fft_segment(void *audio_segment_buffer_orig) { // create a new copy of the buffer so we don't access the space being used by VLC uint8_t *audio_segment_buffer = (uint8_t *) malloc(sizeof(audio_segment_buffer_orig)); memcpy(audio_segment_buffer, audio_segment_buffer_orig, sizeof(audio_segment_buffer_orig)); // create and input into an FFT // an fftw_complex is 2D matrix -- one dimension represents the real components, the other complex. fftw_complex in[NUM_SAMPLES_PER_FFT]; fftw_complex out[NUM_SAMPLES_PER_FFT]; int win_start_index = 0; int win_n = 0; while (win_start_index < NUM_SAMPLES_PER_FFT) { while (win_n < WINDOW_SAMPLE_SIZE) { in[win_start_index + win_n][0] = audio_segment_buffer[win_n] * hamming_window(win_n, WINDOW_SAMPLE_SIZE); win_n++; } win_n = 0; win_start_index += WINDOW_SAMPLE_SIZE / 2; } // establish complex component of the input matrix for (int i = 0; i < NUM_SAMPLES_PER_FFT; i++) { in[i][1] = 0; } fftw_plan plan; plan = fftw_plan_dft_1d(NUM_SAMPLES_PER_FFT, in, out, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute(plan); double frequency_magnitude_dB[NUM_SAMPLES_PER_FFT]; FILE* fft_out_file = fopen("fft_out.dat", "a"); // test output of frequency data for (int i = 0; i < NUM_SAMPLES_PER_FFT; i++) { // calculate the magnitude of the sample, then convert it to a logarithmic scale // to represent as a decibel frequency_magnitude_dB[i] = 20 * log10(sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1])); fprintf(fft_out_file, "%3d,%f ", i * (SAMPLING_FREQUENCY / NUM_SAMPLES_PER_FFT), frequency_magnitude_dB[i]); } fprintf(fft_out_file, "\n"); fclose(fft_out_file); }
int main(int argc, char *argv[]) { calculate_sample_count(); node_type_t type = 0; int port; int ss; struct sockaddr_in addr; data_t d; int s; int status = 0; pthread_t th; complex double *X = (complex double *)malloc(sizeof(complex double) * SAMPLE); complex double *Y = (complex double *)malloc(sizeof(complex double) * SAMPLE); complex short *data = (complex short *)malloc(sizeof(complex short) * N); sample_t *buf = (sample_t *)malloc(sizeof(sample_t) * SAMPLE); sample_t *prev_data = (sample_t *)malloc(sizeof(sample_t) * SAMPLE / 2); char response_send, response_recv; int m, n; if (argc == 2) { type = SERVER; } else if (argc == 3) { type = CLIENT; } else { fprintf(stderr, "Usage: %s [ip address] <port>", argv[1]); exit(1); } port = atoi(argv[argc - 1]); ss = socket(PF_INET, SOCK_STREAM, 0); if (ss == -1) die("socket"); addr.sin_family = AF_INET; addr.sin_port = htons(port); d.socket_number = &ss; d.s = &s; d.status = &status; switch (type) { case SERVER: addr.sin_addr.s_addr = INADDR_ANY; if (bind(ss, (struct sockaddr *)&addr, sizeof(addr)) == -1) die("bind"); if (listen(ss, 10) == -1) die("listen"); if (pthread_create(&th, NULL, accept_connection, (void *)&d) != 0) die("pthread_create"); fprintf(stderr, "Waiting...\n"); break; case CLIENT: if (inet_aton(argv[1], &addr.sin_addr) == 0) die("inet_aton"); if (connect(ss, (struct sockaddr *)&addr, sizeof(addr)) == -1) die("connect"); s = ss; status = 1; fprintf(stderr, "Connected to %s:%d.\n", argv[1], port); break; default: break; } memset(prev_data, 0, sizeof(sample_t) * SAMPLE / 2); while (1) { m = read_n(0, sizeof(sample_t) * SAMPLE / 2, buf + SAMPLE / 2); if (m == 0) break; if (status == 1) { memcpy(buf, prev_data, sizeof(sample_t) * SAMPLE / 2); memcpy(prev_data, buf + SAMPLE / 2, sizeof(sample_t) * SAMPLE / 2); hamming_window(buf, SAMPLE); sample_to_complex(buf, X, SAMPLE); fft(X, Y, SAMPLE); cut_off(data, Y, FREQ_MIN, FREQ_MAX, SAMPLE); set_response_with_data(&response_send, data, N); send(s, &response_send, sizeof(char), 0); switch (response_send) { case RES_OK: case RES_OK_TO_SI: write_n(s, sizeof(complex short) * N, data); // n = send(s, data, sizeof(complex short) * N, 0); break; case RES_SI: memset(prev_data, 0, sizeof(sample_t) * SAMPLE / 2); break; default: break; } // n = recv(s, &response_recv, sizeof(char), 0); n = read_n(s, sizeof(char), &response_recv); if (n == -1) die("recv"); if (n == 0) break; switch (response_recv) { case RES_OK: case RES_OK_TO_SI: n = read_n(s, sizeof(complex short) * N, data); // n = recv(s, data, sizeof(complex short) * N, 0); if (n == -1) die("recv"); if (n == 0) break; re_cut_off(data, Y, FREQ_MIN, FREQ_MAX, SAMPLE); ifft(Y, X, SAMPLE); complex_to_sample(X, buf, SAMPLE); re_hamming_window(buf, SAMPLE); write_n(1, sizeof(sample_t) * SAMPLE / 2, buf + SAMPLE / 4); break; case RES_SI: break; default: break; } } } pthread_join(th, NULL); close(ss); return 0; }