diff --git a/examples/Example_Usage.md b/examples/Example_Usage.md index c6d9f46..03db15d 100644 --- a/examples/Example_Usage.md +++ b/examples/Example_Usage.md @@ -227,9 +227,34 @@ francis@12coresx:~$ ffmpeg -f pulse -i 0 -c:a libmp3lame -ab 64k -f mp3 icecast: ## Sending Audio to UDP Target/Port Audio can be sent to a target address on your local area network with the UDP blaster using the `-o udp:targetaddress:port` option. +Note: Any analog audio monitoring will not function properly over UDP port (rate difference issues) -Example: +Example (Short 8k/2): `dsd-fme -fs -o udp:192.168.7.8:23470` -Receiving End: -`socat stdio udp-listen:23470 | play -q -b 16 -r 8000 -c2 -t s16 -` \ No newline at end of file +Receiving End (Short 8k/2): +`socat stdio udp-listen:23470 | play --buffer 640 -q -b 16 -r 8000 -c2 -t s16 -` + +Example (Short 8k/1): +`dsd-fme -f1 -o udp:192.168.7.8:23469` + +Receiving End (Short 8k/1): +`socat stdio udp-listen:23469 | play --buffer 320 -q -b 16 -r 8000 -c1 -t s16 -` + +Example (Float 8k/2): +`dsd-fme -ft -y -o udp:192.168.7.8:23468` + +Receiving End (Float 8k/2): +`socat stdio udp-listen:23468 | play --buffer 1280 -q -b 16 -r 8000 -c2 -t f32 -` + +Example (Float 8k/1): +`dsd-fme -fi -y -o udp:192.168.7.8:23467` + +Receiving End (Float 8k/1): +`socat stdio udp-listen:23467 | play --buffer 640 -q -b 16 -r 8000 -c1 -t f32 -` + +Note: --buffer option in play is calculated by (channels * samples * sizeof(samples)), +where samples is 160 for mono, 320 for stereo, and short samples are 2 and float samples are 4. +This is vital to prevent 'lag' or cut-off audio when the UDP audio doesn't fill the default buffer size. + +Note2: Be sure to start the receiving end AFTER starting DSD-FME. If DSD-FME is restarted, make sure to restart the receiving end as well, as socat/UDP closes the UDP port listening when DSD-FME closes the UDP socket. \ No newline at end of file diff --git a/src/dsd_rigctl.c b/src/dsd_rigctl.c index 404ea69..24f9f90 100644 --- a/src/dsd_rigctl.c +++ b/src/dsd_rigctl.c @@ -291,16 +291,16 @@ int udp_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * d //listen with: //short 8k/2 - //socat stdio udp-listen:23456 | play -q -b 16 -r 8000 -c2 -t s16 - + //socat stdio udp-listen:23456 | play --buffer 320*2 -q -b 16 -r 8000 -c2 -t s16 - - //short 48k/2 - //socat stdio udp-listen:23456 | play -q -b 16 -r 48000 -c2 -t s16 - + //short 8k/1 + //socat stdio udp-listen:23456 | play --buffer 160*2 -q -b 16 -r 48000 -c2 -t s16 - //float 8k/2 - //socat stdio udp-listen:23456 | play -q -e float -b 32 -r 8000 -c2 -t f32 - + //socat stdio udp-listen:23456 | play --buffer 320*4 -q -e float -b 32 -r 8000 -c2 -t f32 - //float 8k/1 - //socat stdio udp-listen:23456 | play -q -e float -b 32 -r 8000 -c1 -t f32 - + //socat stdio udp-listen:23456 | play --buffer 160*4 -q -e float -b 32 -r 8000 -c1 -t f32 - //send audio or data to socket err = sendto(opts->udp_sockfd, data, nsam, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in)); @@ -311,39 +311,38 @@ int udp_socket_blaster(dsd_opts * opts, dsd_state * state, size_t nsam, void * d int udp_socket_connect(dsd_opts * opts, dsd_state * state) { UNUSED(state); - UNUSED(opts); - int handle, err; //convert handle and address to state variables - handle = err = 0; - unsigned short udp_port = opts->udp_portno; - opts->udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (opts->udp_sockfd < 0) //is this correct? + long int err = 0; + err = opts->udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (err < 0) { - fprintf (stderr, " UDP Socket Error \n"); - return (handle); + fprintf (stderr, " UDP Socket Error %ld\n", err); + return (err); } + + // Don't think this is needed, but doesn't seem to hurt to keep it here either + int broadcastEnable = 1; + err = setsockopt(opts->udp_sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); + if (err < 0) + { + fprintf (stderr, " UDP Broadcast Set Error %ld\n", err); + return (err); + } + memset((char * ) & address, 0, sizeof(address)); address.sin_family = AF_INET; err = address.sin_addr.s_addr = inet_addr(opts->udp_hostname); - if (err < 0) + if (err < 0) //error in this context reports back 32-bit inet_addr reversed order byte pairs { - fprintf (stderr, " UDP inet_addr Error \n"); - return (err); - } - address.sin_port = htons(udp_port); - if (err < 0) - { - fprintf (stderr, " UDP htons Error \n"); + fprintf (stderr, " UDP inet_addr Error %ld\n", err); return (err); } - // For some reason, setting a broadcast to all isn't working - // int broadcastEnable = 1; - // err = setsockopt(opts->udp_sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)); - // if (err < 0) - // { - // fprintf (stderr, " UDP Broadcast Set Error \n"); - // return (err); - // } + address.sin_port = htons(opts->udp_portno); + if (err < 0) + { + fprintf (stderr, " UDP htons Error %ld\n", err); + return (err); + } } diff --git a/src/edacs-fme.c b/src/edacs-fme.c index ea2ee0d..c2f5947 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -625,6 +625,10 @@ void edacs(dsd_opts * opts, dsd_state * state) command = 0; #endif + //disable analog calls on UDP Audio Output + if (opts->audio_out_type == 3 && command == 0xEE) + command = 0; + //this is working now with the new import setup if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block {