00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <unistd.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <pthread.h>
00027 #include <stdint.h>
00028 #include <semaphore.h>
00029 #include "audio_loopback.h"
00030
00031 #include "utility.h"
00032
00033
00034
00035
00036
00038 typedef enum audio_loopback_thread_state_te {
00039 AUDIO_LOOPBACK_STOP,
00040 AUDIO_LOOPBACK_RUN
00041 } audio_loopback_thread_state_te;
00042
00044 typedef struct audio_loopback_ts {
00046 p_audio_device audio_device;
00048 audio_loopback_thread_state_te run;
00050 double *audio_data;
00053 uint32_t dst_samples;
00055 uint32_t src_samples;
00057 pthread_t play_id;
00059 pthread_t convert_id;
00060 } audio_loopback_ts;
00061
00062
00063
00064
00065
00066 static audio_loopback_ts loopback;
00067 static pthread_cond_t write_segment_cond[AUDIO_BUFFER_SEGMENTS] = {PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER};
00068 static pthread_mutex_t write_segment_mutex[AUDIO_BUFFER_SEGMENTS] = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
00069 static sem_t loopback_trigger;
00070
00071
00072
00073
00074
00075 static void audio_loopback_thr(void *param);
00076 static void audio_loopback_convert_thr(void *param);
00077 static void audio_loopback_trigger(void);
00078
00079
00080
00081
00082 int32_t audio_loopback_start(te_audio_device_types device_type,
00083 const char *device_name,
00084 uint32_t segment_size,
00085 int32_t sample_frequency)
00086 {
00087 loopback.audio_data = NULL;
00088 if(NULL != (loopback.audio_device = audio_create(device_type,
00089 AUDIO_DEVICE_PLAY,
00090 device_name,
00091 sample_frequency))) {
00092 audio_open(loopback.audio_device);
00093 audio_init(loopback.audio_device);
00094 loopback.dst_samples = audio_device_samples_get(loopback.audio_device);
00095 loopback.src_samples = segment_size;
00096 loopback.audio_data = malloc((size_t)(AUDIO_BUFFER_SEGMENTS * loopback.dst_samples * sizeof(double)));
00097 loopback.run = AUDIO_LOOPBACK_RUN;
00098 sem_init(&loopback_trigger, 0, 0);
00099 (void)pthread_create(&loopback.play_id, NULL, (void*)&audio_loopback_thr, NULL);
00100 (void)pthread_create(&loopback.convert_id, NULL, (void*)&audio_loopback_convert_thr, NULL);
00101 }
00102 return 0;
00103 }
00104
00105 static void audio_loopback_trigger(void)
00106 {
00107 (void)sem_post(&loopback_trigger);
00108 }
00109
00110 int32_t audio_loopback_stop(void)
00111 {
00112 loopback.run = AUDIO_LOOPBACK_STOP;
00113 pthread_join(loopback.convert_id, NULL);
00114 pthread_join(loopback.play_id, NULL);
00115 free(loopback.audio_data);
00116 loopback.audio_data = NULL;
00117 (void)audio_destroy(&loopback.audio_device);
00118 return 0;
00119 }
00120
00121 void audio_loopback_feed(const double *src)
00122 {
00123 double *dst;
00124 static te_audio_segments buffer_segment = BUFFER_SEGMENT_1;
00125
00126 if(NULL != loopback.audio_data) {
00127 dst = &loopback.audio_data[buffer_segment * loopback.dst_samples];
00128 memcpy(dst, src, loopback.dst_samples);
00129 pthread_cond_signal(&write_segment_cond[buffer_segment]);
00130 buffer_segment++;
00131 if(buffer_segment >= AUDIO_BUFFER_SEGMENTS) {
00132 buffer_segment = BUFFER_SEGMENT_1;
00133 }
00134 }
00135 }
00136
00137 static void audio_loopback_thr(void *param)
00138 {
00139 static te_audio_segments buffer_segment;
00140 static int32_t triggered = 0;
00141
00142 buffer_segment = BUFFER_SEGMENT_1;
00143 while(loopback.run == AUDIO_LOOPBACK_RUN) {
00144 if(triggered == 0) {
00145 (void)sem_wait(&loopback_trigger);
00146 triggered = 1;
00147 }
00148 audio_play(loopback.audio_device, buffer_segment);
00149 buffer_segment++;
00150 if(buffer_segment >= AUDIO_BUFFER_SEGMENTS) {
00151 buffer_segment = BUFFER_SEGMENT_1;
00152 }
00153 }
00154 pthread_cond_signal(&write_segment_cond[0]);
00155 pthread_cond_signal(&write_segment_cond[1]);
00156 pthread_exit(NULL);
00157 }
00158
00159 static void audio_loopback_convert_thr(void *param)
00160 {
00161 static te_audio_segments buffer_segment;
00162 double *audio_data;
00163
00164 buffer_segment = BUFFER_SEGMENT_1;
00165 while(loopback.run == AUDIO_LOOPBACK_RUN) {
00166 pthread_cond_wait(&write_segment_cond[buffer_segment], &write_segment_mutex[buffer_segment]);
00167
00168 audio_data = &loopback.audio_data[buffer_segment * loopback.dst_samples];
00169
00170 audio_double2raw(loopback.audio_device, buffer_segment, audio_data);
00171 audio_loopback_trigger();
00172 pthread_mutex_unlock(&write_segment_mutex[buffer_segment]);
00173 buffer_segment++;
00174 if(buffer_segment >= AUDIO_BUFFER_SEGMENTS) {
00175 buffer_segment = BUFFER_SEGMENT_1;
00176 }
00177 }
00178 pthread_exit(NULL);
00179 }
00180