本文共 7310 字,大约阅读时间需要 24 分钟。
#include <errno.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <netdb.h> | |
#include <fcntl.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <netinet/in.h> | |
#include <alsa/asoundlib.h> | |
#define UDP_TARGET_HOST "127.0.0.1" | |
#define UDP_TARGET_PORT "4001" | |
#define UDP_PACKET_SIZE 64 | |
#define ALSA_SAMPLE_RATE 8000 | |
#define ALSA_CHANNELS 1 | |
main (int argc, char *argv[]) { | |
int err; | |
int buffer_frames = 128; | |
struct addrinfo hints; | |
memset(&hints,0,sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_DGRAM; | |
hints.ai_protocol = 0; | |
hints.ai_flags = AI_ADDRCONFIG; | |
struct addrinfo* res=0; | |
getaddrinfo(UDP_TARGET_HOST, UDP_TARGET_PORT, &hints, &res); | |
int sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol); | |
if (sock==-1) { | |
fprintf(stderr, "cannot create udp socket (%s)\n", strerror(errno)); | |
return -1; | |
} | |
snd_pcm_t *capture_handle; | |
snd_pcm_hw_params_t *hw_params; | |
snd_pcm_format_t format = SND_PCM_FORMAT_A_LAW; | |
if ((err = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0) { | |
fprintf(stderr, "cannot open audio device %s (%s)\n", argv[1], snd_strerror(err)); | |
exit (1); | |
} | |
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { | |
fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); | |
exit (1); | |
} | |
snd_pcm_hw_params_any(capture_handle, hw_params); | |
snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
snd_pcm_hw_params_set_format(capture_handle, hw_params, format); | |
snd_pcm_hw_params_set_rate(capture_handle, hw_params, ALSA_SAMPLE_RATE, 0); | |
snd_pcm_hw_params_set_channels(capture_handle, hw_params, ALSA_CHANNELS); | |
snd_pcm_hw_params_set_period_size(capture_handle, hw_params, 32, 0); | |
snd_pcm_hw_params(capture_handle, hw_params); | |
snd_pcm_hw_params_free(hw_params); | |
if ((err = snd_pcm_prepare(capture_handle)) < 0) { | |
fprintf(stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror(err)); | |
exit (1); | |
} | |
uint8_t buffer[UDP_PACKET_SIZE]; | |
while (1) { | |
if ((err = snd_pcm_readi(capture_handle, buffer, sizeof(buffer))) != sizeof(buffer)) { | |
fprintf(stderr, "read from audio interface failed (%s)\n", snd_strerror(err)); | |
break; | |
} | |
if (sendto(sock, buffer, sizeof(buffer), 0, res->ai_addr,res->ai_addrlen)==-1) { | |
fprintf(stderr, "udp sendto failed(%s)\n", strerror(errno)); | |
break; | |
} | |
} | |
snd_pcm_close(capture_handle); | |
exit(0); | |
} |
#include <errno.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <netdb.h> | |
#include <fcntl.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <netinet/in.h> | |
#include <time.h> | |
#define UDP_TARGET_HOST "127.0.0.1" | |
#define UDP_TARGET_PORT "4001" | |
#define UDP_PACKET_SIZE 64 | |
#define FILE_SAMPLE_RATE 8000 | |
int8_t alaw_encode(int16_t number) | |
{ | |
/* | |
* Taken from: | |
* http://dystopiancode.blogspot.de/2012/02/pcm-law-and-u-law-companding-algorithms.html | |
*/ | |
const uint16_t ALAW_MAX = 0xFFF; | |
uint16_t mask = 0x800; | |
uint8_t sign = 0; | |
uint8_t position = 11; | |
uint8_t lsb = 0; | |
if (number < 0) { | |
number = -number; | |
sign = 0x80; | |
} | |
if (number > ALAW_MAX) { | |
number = ALAW_MAX; | |
} | |
for (; ((number & mask) != mask && position >= 5); mask >>= 1, position--); | |
lsb = (number >> ((position == 4) ? (1) : (position - 4))) & 0x0f; | |
return (sign | ((position - 4) << 4) | lsb) ^ 0x55; | |
} | |
int main(int argc, char **argv) { | |
struct addrinfo hints; | |
memset(&hints,0,sizeof(hints)); | |
hints.ai_family = AF_UNSPEC; | |
hints.ai_socktype = SOCK_DGRAM; | |
hints.ai_protocol = 0; | |
hints.ai_flags = AI_ADDRCONFIG; | |
struct addrinfo* res=0; | |
getaddrinfo(UDP_TARGET_HOST, UDP_TARGET_PORT, &hints, &res); | |
int fd=socket(res->ai_family,res->ai_socktype,res->ai_protocol); | |
if (fd==-1) { | |
puts(strerror(errno)); | |
return -1; | |
} | |
int readfd = open(argv[1], O_RDONLY); | |
if (!readfd) { perror("could not open file"); } | |
struct timespec t_next_send; | |
clock_gettime(CLOCK_MONOTONIC, &t_next_send); | |
int frame_inteval_us = 1000000 / FILE_SAMPLE_RATE; | |
int frames_per_packet = UDP_PACKET_SIZE; | |
int packet_interval_us = frames_per_packet * frame_inteval_us; | |
int16_t readbuf[UDP_PACKET_SIZE]; | |
int8_t sendbuf[UDP_PACKET_SIZE]; | |
while (1) { | |
int bytes_read = read(readfd, readbuf, sizeof(readbuf)); | |
if (bytes_read<=0) { break; } | |
int i; | |
for (i=0; i<UDP_PACKET_SIZE; i++) { | |
sendbuf[i] = alaw_encode(readbuf[i]/8); | |
} | |
if (sendto(fd, sendbuf, bytes_read/2, 0, res->ai_addr,res->ai_addrlen)==-1) { | |
puts(strerror(errno)); | |
break; | |
} | |
t_next_send.tv_nsec += 1000*packet_interval_us; | |
while (t_next_send.tv_nsec>1000000000UL) { | |
t_next_send.tv_nsec -= 1000000000UL; | |
t_next_send.tv_sec += 1; | |
} | |
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &t_next_send, NULL); | |
} | |
close(readfd); | |
return 0; | |
} |
/* | |
* udp-alaw-sink.c | |
* | |
* Created on: 14.03.2015 | |
* Author: hd | |
*/ | |
#define ALSA_PCM_NEW_HW_PARAMS_API | |
#include <alsa/asoundlib.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#define ALSA_SAMPLE_RATE 8000 | |
#define ALSA_CHANNELS 1 | |
#define UDP_ALAW_PORT 4001 | |
#define UDP_MAX_PACKET_SIZE 1024 | |
int main() { | |
/* create UDP socket */ | |
int sock = socket(AF_INET, SOCK_DGRAM, 0); | |
if (sock < 0) { | |
perror("Opening datagram socket"); | |
exit(1); | |
} | |
struct sockaddr_in server_addr; | |
bzero((char *) &server_addr, sizeof(server_addr)); | |
server_addr.sin_family = AF_INET; | |
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
server_addr.sin_port = htons(UDP_ALAW_PORT); | |
if (bind(sock, (struct sockaddr *) &server_addr, sizeof(server_addr))) { | |
perror("binding datagram socket"); | |
exit(1); | |
} | |
/* open PCM device */ | |
snd_pcm_t *pcm_handle; | |
int rc = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); | |
if (rc < 0) { | |
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); | |
exit(1); | |
} | |
/* set hardware paramters */ | |
snd_pcm_hw_params_t *hw_params; | |
snd_pcm_hw_params_alloca(&hw_params); | |
snd_pcm_hw_params_any(pcm_handle, hw_params); | |
snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_A_LAW); | |
snd_pcm_hw_params_set_channels(pcm_handle, hw_params, ALSA_CHANNELS); | |
snd_pcm_hw_params_set_rate(pcm_handle, hw_params, ALSA_SAMPLE_RATE, 0); | |
snd_pcm_hw_params_set_period_size(pcm_handle, hw_params, 32, 0); | |
rc = snd_pcm_hw_params(pcm_handle, hw_params); | |
if (rc < 0) { | |
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); | |
exit(1); | |
} | |
/* set software paramters */ | |
snd_pcm_sw_params_t *sw_params; | |
snd_pcm_sw_params_malloc(&sw_params); | |
snd_pcm_sw_params_current(pcm_handle, sw_params); | |
snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 64); | |
rc = snd_pcm_sw_params(pcm_handle, sw_params); | |
if (rc < 0) { | |
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); | |
exit(1); | |
} | |
snd_pcm_sw_params_free(sw_params); | |
uint8_t buffer[UDP_MAX_PACKET_SIZE]; | |
struct sockaddr_in client_addr; | |
while (1) { | |
socklen_t client_addr_len = sizeof(client_addr); | |
int send_bytes_avail = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &client_addr_len); | |
int send_pos = 0; | |
while (send_bytes_avail>0) { | |
int rc = snd_pcm_writei(pcm_handle, &buffer[send_pos], send_bytes_avail); | |
if (rc>0) { | |
send_bytes_avail -= rc; | |
send_pos += rc; | |
} else if (rc == -EPIPE) { | |
/* EPIPE means underrun */ | |
snd_pcm_prepare(pcm_handle); | |
} else { // other error | |
break; | |
} | |
} | |
} | |
close(sock); | |
snd_pcm_drain(pcm_handle); | |
snd_pcm_close(pcm_handle); | |
return 0; | |
} |
转载地址:http://gbzji.baihongyu.com/