Beispiel #1
0
void netjack_send_silence( netjack_driver_state_t *netj, int syncstate )
{
    int tx_size = get_sample_size(netj->bitdepth) * netj->playback_channels * netj->net_period_up + sizeof(jacknet_packet_header);
    unsigned int *packet_buf, *packet_bufX;

    packet_buf = alloca( tx_size);
    jacknet_packet_header *tx_pkthdr = (jacknet_packet_header *)packet_buf;
    jacknet_packet_header *rx_pkthdr = (jacknet_packet_header *)netj->rx_buf;

    //framecnt = rx_pkthdr->framecnt;

    netj->reply_port = rx_pkthdr->reply_port;

    // offset packet_bufX by the packetheader.
    packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);

    tx_pkthdr->sync_state = syncstate;
    tx_pkthdr->framecnt = netj->expected_framecnt;

    // memset 0 the payload.
    int payload_size = get_sample_size(netj->bitdepth) * netj->playback_channels * netj->net_period_up;
    memset(packet_bufX, 0, payload_size);

    packet_header_hton(tx_pkthdr);
    if (netj->srcaddress_valid)
    {
	int r;
	if (netj->reply_port)
	    netj->syncsource_address.sin_port = htons(netj->reply_port);

	for( r=0; r<netj->redundancy; r++ )
	    netjack_sendto(netj->outsockfd, (char *)packet_buf, tx_size,
		    0, (struct sockaddr*)&(netj->syncsource_address), sizeof(struct sockaddr_in), netj->mtu);
    }
}
Beispiel #2
0
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int
process (jack_nframes_t nframes, void *arg)
{
    jack_nframes_t net_period;
    int rx_bufsize, tx_bufsize;

    jack_default_audio_sample_t *buf;
    jack_port_t *port;
    JSList *node;
    int chn;
    int size, i;
    const char *porttype;
    int input_fd;

    jack_position_t local_trans_pos;

    uint32_t *packet_buf_tx, *packet_bufX;
    uint32_t *rx_packet_ptr;
    jack_time_t packet_recv_timestamp;

    if( bitdepth == 1000 || bitdepth == 999)
        net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ;
    else
        net_period = (float) nframes / (float) factor;

    rx_bufsize =  get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
    tx_bufsize =  get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);

    /* Allocate a buffer where both In and Out Buffer will fit */
    packet_buf_tx = alloca (tx_bufsize);

    jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx;

    /*
     * for latency==0 we need to send out the packet before we wait on the reply.
     * but this introduces a cycle of latency, when netsource is connected to itself.
     * so we send out before read only in zero latency mode.
     *
     */

    if( latency == 0 ) {
        /* reset packet_bufX... */
        packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

        /* ---------- Send ---------- */
        render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
                                      packet_bufX, net_period, dont_htonl_floats);

        /* fill in packet hdr */
        pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
        pkthdr_tx->transport_frame = local_trans_pos.frame;
        pkthdr_tx->framecnt = framecnt;
        pkthdr_tx->latency = latency;
        pkthdr_tx->reply_port = reply_port;
        pkthdr_tx->sample_rate = jack_get_sample_rate (client);
        pkthdr_tx->period_size = nframes;

        /* playback for us is capture on the other side */
        pkthdr_tx->capture_channels_audio = playback_channels_audio;
        pkthdr_tx->playback_channels_audio = capture_channels_audio;
        pkthdr_tx->capture_channels_midi = playback_channels_midi;
        pkthdr_tx->playback_channels_midi = capture_channels_midi;
        pkthdr_tx->mtu = mtu;
        if( freewheeling != 0 )
            pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
        else
            pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
        //printf("goodness=%d\n", deadline_goodness );

        packet_header_hton (pkthdr_tx);
        if (cont_miss < 3 * latency + 5) {
            int r;
            for( r = 0; r < redundancy; r++ )
                netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
        } else if (cont_miss > 50 + 5 * latency) {
            state_connected = 0;
            packet_cache_reset_master_address( packcache );
            //printf ("Frame %d  \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
            cont_miss = 0;
        }
    }

    /*
     * ok... now the RECEIVE code.
     *
     */


    if( reply_port )
        input_fd = insockfd;
    else
        input_fd = outsockfd;

    // for latency == 0 we can poll.
    if( (latency == 0) || (freewheeling != 0)  ) {
        jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client);
        // Now loop until we get the right packet.
        while(1) {
            jack_nframes_t got_frame;
            if ( ! netjack_poll_deadline( input_fd, deadline ) )
                break;

            packet_cache_drain_socket(packcache, input_fd);

            if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame ))
                if( got_frame == (framecnt - latency) )
                    break;
        }
    } else {
        // normally:
        // only drain socket.
        packet_cache_drain_socket(packcache, input_fd);
    }

    size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp );
    /* First alternative : we received what we expected. Render the data
     * to the JACK ports so it can be played. */
    if (size == rx_bufsize) {
        uint32_t *packet_buf_rx = rx_packet_ptr;
        jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx;
        packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
        // calculate how much time there would have been, if this packet was sent at the deadline.

        int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp);
        packet_header_ntoh (pkthdr_rx);
        deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency;
        //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset );

        if (cont_miss) {
            //printf("Frame %d  \tRecovered from dropouts\n", framecnt);
            cont_miss = 0;
        }
        render_payload_to_jack_ports (bitdepth, packet_bufX, net_period,
                                      capture_ports, capture_srcs, nframes, dont_htonl_floats);

        state_currentframe = framecnt;
        state_recv_packet_queue_time = recv_time_offset;
        state_connected = 1;
        sync_state = pkthdr_rx->sync_state;
        packet_cache_release_packet( packcache, framecnt - latency );
    }
    /* Second alternative : we've received something that's not
     * as big as expected or we missed a packet. We render silence
     * to the ouput ports */
    else {
        jack_nframes_t latency_estimate;
        if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) )
            //if( (state_latency == 0) || (latency_estimate < state_latency) )
            state_latency = latency_estimate;

        // Set the counters up.
        state_currentframe = framecnt;
        //state_latency = framecnt - pkthdr->framecnt;
        state_netxruns += 1;

        //printf ("Frame %d  \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size);
        //printf ("Frame %d  \tPacket missed or incomplete\n", framecnt);
        cont_miss += 1;
        chn = 0;
        node = capture_ports;
        while (node != NULL) {
            port = (jack_port_t *) node->data;
            buf = jack_port_get_buffer (port, nframes);
            porttype = jack_port_type (port);
            if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0)
                for (i = 0; i < nframes; i++)
                    buf[i] = 0.0;
            else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0)
                jack_midi_clear_buffer (buf);
            node = jack_slist_next (node);
            chn++;
        }
    }
    if (latency != 0) {
        /* reset packet_bufX... */
        packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

        /* ---------- Send ---------- */
        render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
                                      packet_bufX, net_period, dont_htonl_floats);

        /* fill in packet hdr */
        pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
        pkthdr_tx->transport_frame = local_trans_pos.frame;
        pkthdr_tx->framecnt = framecnt;
        pkthdr_tx->latency = latency;
        pkthdr_tx->reply_port = reply_port;
        pkthdr_tx->sample_rate = jack_get_sample_rate (client);
        pkthdr_tx->period_size = nframes;

        /* playback for us is capture on the other side */
        pkthdr_tx->capture_channels_audio = playback_channels_audio;
        pkthdr_tx->playback_channels_audio = capture_channels_audio;
        pkthdr_tx->capture_channels_midi = playback_channels_midi;
        pkthdr_tx->playback_channels_midi = capture_channels_midi;
        pkthdr_tx->mtu = mtu;
        if( freewheeling != 0 )
            pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
        else
            pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
        //printf("goodness=%d\n", deadline_goodness );

        packet_header_hton (pkthdr_tx);
        if (cont_miss < 3 * latency + 5) {
            int r;
            for( r = 0; r < redundancy; r++ )
                netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
        } else if (cont_miss > 50 + 5 * latency) {
            state_connected = 0;
            packet_cache_reset_master_address( packcache );
            //printf ("Frame %d  \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
            cont_miss = 0;
        }
    }

    framecnt++;
    return 0;
}