400 | | |
---|
401 | | for ( PortVectorIterator it = m_Ports.begin(); |
---|
402 | | it != m_Ports.end(); |
---|
403 | | ++it ) |
---|
404 | | { |
---|
405 | | if ( (*it)->isDisabled() ) { continue; }; |
---|
406 | | |
---|
407 | | //FIXME: make this into a static_cast when not DEBUG? |
---|
408 | | AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); |
---|
409 | | assert ( pinfo ); // this should not fail!! |
---|
410 | | |
---|
411 | | switch( pinfo->getFormat() ) |
---|
412 | | { |
---|
413 | | case AmdtpPortInfo::E_MBLA: |
---|
414 | | if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) |
---|
415 | | { |
---|
416 | | debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); |
---|
417 | | no_problem = false; |
---|
418 | | } |
---|
419 | | break; |
---|
420 | | case AmdtpPortInfo::E_SPDIF: // still unimplemented |
---|
421 | | break; |
---|
422 | | case AmdtpPortInfo::E_Midi: |
---|
423 | | if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) |
---|
424 | | { |
---|
425 | | debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); |
---|
426 | | no_problem = false; |
---|
427 | | } |
---|
428 | | break; |
---|
429 | | default: // ignore |
---|
430 | | break; |
---|
431 | | } |
---|
432 | | } |
---|
| 409 | updatePortCache(); |
---|
| 410 | |
---|
| 411 | if(!encodeAudioPorts((quadlet_t *)data, offset, nevents)) { |
---|
| 412 | debugError("Could not encode audio ports\n"); |
---|
| 413 | return false; |
---|
| 414 | } |
---|
| 415 | |
---|
| 416 | // for ( PortVectorIterator it = m_Ports.begin(); |
---|
| 417 | // it != m_Ports.end(); |
---|
| 418 | // ++it ) |
---|
| 419 | // { |
---|
| 420 | // if ( (*it)->isDisabled() ) { continue; }; |
---|
| 421 | // |
---|
| 422 | // //FIXME: make this into a static_cast when not DEBUG? |
---|
| 423 | // AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); |
---|
| 424 | // assert ( pinfo ); // this should not fail!! |
---|
| 425 | // |
---|
| 426 | // switch( pinfo->getFormat() ) |
---|
| 427 | // { |
---|
| 428 | // case AmdtpPortInfo::E_MBLA: |
---|
| 429 | // if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) |
---|
| 430 | // { |
---|
| 431 | // debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); |
---|
| 432 | // no_problem = false; |
---|
| 433 | // } |
---|
| 434 | // break; |
---|
| 435 | // case AmdtpPortInfo::E_SPDIF: // still unimplemented |
---|
| 436 | // break; |
---|
| 437 | // case AmdtpPortInfo::E_Midi: |
---|
| 438 | // if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) |
---|
| 439 | // { |
---|
| 440 | // debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); |
---|
| 441 | // no_problem = false; |
---|
| 442 | // } |
---|
| 443 | // break; |
---|
| 444 | // default: // ignore |
---|
| 445 | // break; |
---|
| 446 | // } |
---|
| 447 | // } |
---|
528 | | |
---|
529 | | assert ( nevents + offset <= p->getBufferSize() ); |
---|
530 | | |
---|
531 | | buffer+=offset; |
---|
532 | | |
---|
533 | | j=0; |
---|
534 | | if(read>3) { |
---|
535 | | for (j = 0; j < read-3; j += 4) { |
---|
536 | | asm("movups %[floatbuff], %%xmm0\n\t" |
---|
537 | | "mulps %[ssemult], %%xmm0\n\t" |
---|
538 | | "cvttps2pi %%xmm0, %[out1]\n\t" |
---|
539 | | "movhlps %%xmm0, %%xmm0\n\t" |
---|
540 | | "psrld $8, %[out1]\n\t" |
---|
541 | | "cvttps2pi %%xmm0, %[out2]\n\t" |
---|
542 | | "por %[mmxmask], %[out1]\n\t" |
---|
543 | | "psrld $8, %[out2]\n\t" |
---|
544 | | "por %[mmxmask], %[out2]\n\t" |
---|
545 | | : [out1] "=&y" (*(v2si*)&out[0]), |
---|
546 | | [out2] "=&y" (*(v2si*)&out[2]) |
---|
547 | | : [floatbuff] "m" (*(v4sf*)buffer), |
---|
548 | | [ssemult] "x" (*(v4sf*)sse_multiplier), |
---|
549 | | [mmxmask] "y" (*(v2si*)sse_mask) |
---|
550 | | : "xmm0"); |
---|
551 | | buffer += 4; |
---|
552 | | *target_event = htonl(out[0]); |
---|
553 | | target_event += m_dimension; |
---|
554 | | *target_event = htonl(out[1]); |
---|
555 | | target_event += m_dimension; |
---|
556 | | *target_event = htonl(out[2]); |
---|
557 | | target_event += m_dimension; |
---|
558 | | *target_event = htonl(out[3]); |
---|
559 | | target_event += m_dimension; |
---|
560 | | } |
---|
561 | | } |
---|
562 | | for(; j < read; ++j) { |
---|
563 | | // don't care for overflow |
---|
564 | | float v = *buffer * multiplier; // v: -231 .. 231 |
---|
565 | | unsigned int tmp = (int)v; |
---|
566 | | *target_event = htonl((tmp >> 8) | 0x40000000); |
---|
567 | | |
---|
568 | | buffer++; |
---|
569 | | target_event += m_dimension; |
---|
570 | | } |
---|
571 | | |
---|
572 | | asm volatile("emms"); |
---|
573 | | break; |
---|
574 | | } |
---|
575 | | break; |
---|
576 | | } |
---|
577 | | |
---|
578 | | return 0; |
---|
579 | | } |
---|
580 | | |
---|
581 | | #else |
---|
582 | | |
---|
583 | | int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, |
---|
584 | | unsigned int offset, unsigned int nevents ) |
---|
585 | | { |
---|
586 | | unsigned int j=0; |
---|
587 | | |
---|
588 | | quadlet_t *target_event; |
---|
589 | | |
---|
590 | | target_event= ( quadlet_t * ) ( data + p->getPosition() ); |
---|
591 | | |
---|
592 | | switch ( p->getDataType() ) |
---|
593 | | { |
---|
594 | | default: |
---|
595 | | debugError("bad type: %d\n", p->getDataType()); |
---|
596 | | return -1; |
---|
597 | | case Port::E_Int24: |
---|
598 | | { |
---|
599 | | quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); |
---|
| 652 | /** |
---|
| 653 | * @brief encodes all audio ports in the cache to events |
---|
| 654 | * @param data |
---|
| 655 | * @param offset |
---|
| 656 | * @param nevents |
---|
| 657 | * @return |
---|
| 658 | */ |
---|
| 659 | bool |
---|
| 660 | AmdtpTransmitStreamProcessor::encodeAudioPorts(quadlet_t *data, |
---|
| 661 | unsigned int offset, |
---|
| 662 | unsigned int nevents) |
---|
| 663 | { |
---|
| 664 | unsigned int j=0; |
---|
| 665 | |
---|
| 666 | quadlet_t *target_event; |
---|
| 667 | unsigned int i; |
---|
| 668 | for (i = 0; i < m_nb_audio_ports; i++) { |
---|
| 669 | struct _MBLA_port_cache p = m_audio_ports.at(i); |
---|
| 670 | target_event = (quadlet_t *)(data + i); |
---|
| 671 | assert(nevents + offset <= p.buffer_size ); |
---|
| 672 | |
---|
| 673 | switch ( p.type ) |
---|
| 674 | { |
---|
| 675 | case Port::E_Float: |
---|
| 676 | { |
---|
| 677 | float *buffer = (float *)(p.buffer); |
---|
| 678 | buffer += offset; |
---|
| 679 | |
---|
| 680 | for (j = 0;j < nevents; j += 1) // decode max nsamples |
---|
| 681 | { |
---|
| 682 | // don't care for overflow |
---|
| 683 | float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER; |
---|
| 684 | unsigned int tmp = ((int) v); |
---|
| 685 | *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); |
---|
| 686 | buffer++; |
---|
| 687 | target_event += m_dimension; |
---|
| 688 | } |
---|
| 689 | } |
---|
| 690 | break; |
---|
| 691 | case Port::E_Int24: |
---|
| 692 | { |
---|
| 693 | uint32_t *buffer = (uint32_t *)(p.buffer); |
---|
| 694 | buffer += offset; |
---|
| 695 | |
---|
| 696 | for (j = 0; j < nevents; j += 1) // decode max nsamples |
---|
| 697 | { |
---|
| 698 | *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000); |
---|
| 699 | buffer++; |
---|
| 700 | target_event += m_dimension; |
---|
| 701 | } |
---|
| 702 | } |
---|
| 703 | break; |
---|
| 704 | default: |
---|
| 705 | debugError("bad type: %d\n", m_audio_ports.at(i).type); |
---|
| 706 | return false; |
---|
| 707 | } |
---|
| 708 | } |
---|
| 709 | return true; |
---|
| 710 | } |
---|
| 711 | |
---|
| 712 | |
---|
| 713 | bool |
---|
| 714 | AmdtpTransmitStreamProcessor::initPortCache() { |
---|
| 715 | // make use of the fact that audio ports are the first ports in |
---|
| 716 | // the cluster as per AMDTP. so we can sort the ports by position |
---|
| 717 | // and have very efficient lookups: |
---|
| 718 | // m_float_ports.at(i).buffer -> audio stream i buffer |
---|
| 719 | m_nb_audio_ports = 0; |
---|
| 720 | m_audio_ports.clear(); |
---|
| 721 | |
---|
| 722 | m_nb_midi_ports = 0; |
---|
| 723 | |
---|
| 724 | for(PortVectorIterator it = m_Ports.begin(); |
---|
| 725 | it != m_Ports.end(); |
---|
| 726 | ++it ) |
---|
| 727 | { |
---|
| 728 | AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); |
---|
| 729 | assert(pinfo); // this should not fail!! |
---|
| 730 | |
---|
| 731 | switch( pinfo->getFormat() ) |
---|
| 732 | { |
---|
| 733 | case AmdtpPortInfo::E_MBLA: |
---|
| 734 | m_nb_audio_ports++; |
---|
| 735 | break; |
---|
| 736 | case AmdtpPortInfo::E_SPDIF: // still unimplemented |
---|
| 737 | break; |
---|
| 738 | case AmdtpPortInfo::E_Midi: |
---|
| 739 | m_nb_midi_ports++; |
---|
| 740 | break; |
---|
| 741 | default: // ignore |
---|
| 742 | break; |
---|
| 743 | } |
---|
| 744 | } |
---|
| 745 | |
---|
| 746 | unsigned int idx; |
---|
| 747 | for (idx = 0; idx < m_nb_audio_ports; idx++) { |
---|
| 748 | for(PortVectorIterator it = m_Ports.begin(); |
---|
| 749 | it != m_Ports.end(); |
---|
| 750 | ++it ) |
---|
| 751 | { |
---|
| 752 | AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); |
---|
| 753 | debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n", |
---|
| 754 | idx, (*it)->getName().c_str(), pinfo->getPosition()); |
---|
| 755 | if(pinfo->getPosition() == idx) { |
---|
| 756 | struct _MBLA_port_cache p; |
---|
| 757 | p.port = dynamic_cast<AmdtpAudioPort *>(*it); |
---|
| 758 | if(p.port == NULL) { |
---|
| 759 | debugError("Port is not an AmdtpAudioPort!\n"); |
---|
| 760 | return false; |
---|
| 761 | } |
---|
| 762 | // p.position = pinfo->getPosition(); |
---|
| 763 | p.buffer = NULL; // to be filled by updatePortCache |
---|
| 764 | p.type = (*it)->getDataType(); |
---|
| 765 | #ifdef DEBUG |
---|
| 766 | p.buffer_size = (*it)->getBufferSize(); |
---|
| 767 | #endif |
---|
| 768 | |
---|
| 769 | m_audio_ports.push_back(p); |
---|
| 770 | debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n", |
---|
| 771 | p.port->getName().c_str(), idx); |
---|
| 772 | goto next_index; |
---|
| 773 | } |
---|
| 774 | } |
---|
| 775 | debugError("No MBLA port found for position %d\n", idx); |
---|
| 776 | return false; |
---|
| 777 | next_index: |
---|
| 778 | continue; |
---|
| 779 | } |
---|
| 780 | |
---|
| 781 | return true; |
---|
| 782 | } |
---|
| 783 | |
---|
| 784 | void |
---|
| 785 | AmdtpTransmitStreamProcessor::updatePortCache() { |
---|
| 786 | unsigned int idx; |
---|
| 787 | for (idx = 0; idx < m_nb_audio_ports; idx++) { |
---|
| 788 | AmdtpAudioPort *port = m_audio_ports.at(idx).port; |
---|
| 789 | m_audio_ports.at(idx).buffer = port->getBufferAddress(); |
---|
| 790 | } |
---|
| 791 | } |
---|
| 792 | |
---|