comparison libinterp/dldfcn/audiodevinfo.cc @ 19578:827394ba8eb2

Backed out changeset 5f313345912f Undo accidental changes from previous changeset.
author John W. Eaton <jwe@octave.org>
date Wed, 07 Jan 2015 18:11:05 -0500
parents 5f313345912f
children c5b8a91baec6
comparison
equal deleted inserted replaced
19577:5f313345912f 19578:827394ba8eb2
456 void init_fn (void); 456 void init_fn (void);
457 void set_y (const octave_value& y); 457 void set_y (const octave_value& y);
458 void set_y (octave_function *fn); 458 void set_y (octave_function *fn);
459 void set_y (std::string fn); 459 void set_y (std::string fn);
460 Matrix& get_y (void); 460 Matrix& get_y (void);
461 RowVector get_left (void) const; 461 RowVector *get_left (void);
462 RowVector get_right (void) const; 462 RowVector *get_right (void);
463 void set_fs (int fs); 463 void set_fs (int fs);
464 int get_fs (void); 464 int get_fs (void);
465 void set_nbits (int nbits); 465 void set_nbits (int nbits);
466 int get_nbits (void); 466 int get_nbits (void);
467 void set_id (int id); 467 void set_id (int id);
508 508
509 DECLARE_OCTAVE_ALLOCATOR 509 DECLARE_OCTAVE_ALLOCATOR
510 DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA 510 DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
511 }; 511 };
512 512
513 #define BUFFER_SIZE 8192 513 #define BUFFER_SIZE 512
514 514
515 DEFINE_OCTAVE_ALLOCATOR (audioplayer); 515 DEFINE_OCTAVE_ALLOCATOR (audioplayer);
516 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer"); 516 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer");
517 517
518 int 518 int
530 octave_play_callback (const void *, void *output, unsigned long frames, 530 octave_play_callback (const void *, void *output, unsigned long frames,
531 const PaStreamCallbackTimeInfo *, 531 const PaStreamCallbackTimeInfo *,
532 PaStreamCallbackFlags, void *data) 532 PaStreamCallbackFlags, void *data)
533 { 533 {
534 audioplayer *player = static_cast<audioplayer *> (data); 534 audioplayer *player = static_cast<audioplayer *> (data);
535 535 int big_endian = is_big_endian ();
536 if (! player) 536 octave_value_list args, retval;
537 { 537 args(0) = frames;
538 error ("audio player callback function called without player"); 538 retval = feval (player->octave_callback_function, args, 1);
539 return paAbort; 539 RowVector sound_l, sound_r;
540 }
541
542 octave_value_list retval = feval (player->octave_callback_function,
543 ovl (static_cast<double> (frames)), 1);
544
545 if (error_state || retval.length () < 2)
546 {
547 error ("audio player callback function failed");
548 return paAbort;
549 }
550
551 Matrix sound = retval(0).matrix_value (); 540 Matrix sound = retval(0).matrix_value ();
552 int return_status = retval(1).int_value (); 541 int return_status = retval(1).int_value ();
553 542 sound_l.resize (frames);
554 if (error_state || frames != sound.rows () 543 sound_r.resize (frames);
555 || sound.columns () < 1 || sound.columns () > 2) 544 if (sound.cols () == 1)
556 { 545 {
557 error ("audio player callback function failed"); 546 for (unsigned long i = 0; i < frames; i++)
558 return paAbort; 547 {
559 } 548 sound_l(i) = sound(i, 0);
560 549 sound_r(i) = sound(i, 0);
561 double scale_factor = 1.0; 550 }
562 551 }
563 switch (player->get_nbits ()) 552 else if (sound.cols () == 2)
564 { 553 {
565 case 8: 554 for (unsigned long i = 0; i < frames; i++)
566 scale_factor = pow (2.0, 7) - 1.0; 555 {
567 break; 556 sound_l(i) = sound(i, 0);
568 557 sound_r(i) = sound(i, 1);
569 case 16: 558 }
570 scale_factor = pow (2.0, 15) - 1.0; 559 }
571 break; 560 else
572 561 return paAbort;
573 case 24: 562
574 scale_factor = pow (2.0, 23) - 1.0; 563 for (unsigned long i = 0; i < frames; i++)
575 break; 564 {
576 565 if (player->get_nbits () == 8)
577 default: 566 {
578 error ("invalid player bit depth in callback function"); 567 int8_t *buffer = static_cast<int8_t *> (output);
579 break; 568 buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 7) - 1);
580 } 569 buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 7) - 1);
581 570 }
582 sound = sound * scale_factor; 571 else if (player->get_nbits () == 16)
583 572 {
584 const RowVector sound_l = (sound.column (0)).transpose (); 573 int16_t *buffer = static_cast<int16_t *> (output);
585 574 buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 15) - 1);
586 const RowVector sound_r = (sound.columns () == 1) 575 buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 15) - 1);
587 ? sound_l : (sound.column (1)).transpose (); 576 }
588 577 else if (player->get_nbits () == 24)
589 const double *p_l = sound_l.data (); 578 {
590 const double *p_r = sound_r.data (); 579 uint8_t *buffer = static_cast<uint8_t *> (output);
591 580 int32_t sample_l = sound_l.elem (i) * (pow (2.0, 23) - 1);
592 switch (player->get_nbits ()) 581 int32_t sample_r = sound_r.elem (i) * (pow (2.0, 23) - 1);
593 { 582 sample_l &= 0x00ffffff;
594 case 8: 583 sample_r &= 0x00ffffff;
595 { 584 // FIXME: Would a mask work better?
596 int8_t *buffer = static_cast<int8_t *> (output); 585 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
597 586 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
598 for (unsigned long i = 0; i < frames; i++) 587 buffer[i * 6 + 0] = _sample_l[0 + big_endian];
599 { 588 buffer[i * 6 + 1] = _sample_l[1 + big_endian];
600 buffer[2*i] = p_l[i]; 589 buffer[i * 6 + 2] = _sample_l[2 + big_endian];
601 buffer[2*i+1] = p_r[i]; 590 buffer[i * 6 + 3] = _sample_r[0 + big_endian];
602 } 591 buffer[i * 6 + 4] = _sample_r[1 + big_endian];
603 } 592 buffer[i * 6 + 5] = _sample_r[2 + big_endian];
604 break; 593 }
605 594 }
606 case 16:
607 {
608 int16_t *buffer = static_cast<int16_t *> (output);
609
610 for (unsigned long i = 0; i < frames; i++)
611 {
612 buffer[2*i] = p_l[i];
613 buffer[2*i+1] = p_r[i];
614 }
615 }
616 break;
617
618 case 24:
619 {
620 int big_endian = is_big_endian ();
621
622 uint8_t *buffer = static_cast<uint8_t *> (output);
623
624 for (unsigned long i = 0; i < frames; i++)
625 {
626 int32_t sample_l = p_l[i];
627 int32_t sample_r = p_r[i];
628
629 sample_l &= 0x00ffffff;
630 sample_r &= 0x00ffffff;
631
632 // FIXME: Would a mask work better?
633 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
634 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
635
636 unsigned long offset = i * 6;
637
638 buffer[offset+0] = _sample_l[0+big_endian];
639 buffer[offset+1] = _sample_l[1+big_endian];
640 buffer[offset+2] = _sample_l[2+big_endian];
641
642 buffer[offset+3] = _sample_r[0+big_endian];
643 buffer[offset+4] = _sample_r[1+big_endian];
644 buffer[offset+5] = _sample_r[2+big_endian];
645 }
646 }
647 break;
648
649 default:
650 error ("invalid player bit depth in callback function");
651 break;
652 }
653
654 return return_status; 595 return return_status;
655 } 596 }
656 597
657 static int 598 static int
658 portaudio_play_callback (const void *, void *output, unsigned long frames, 599 portaudio_play_callback (const void *, void *output, unsigned long frames,
659 const PaStreamCallbackTimeInfo*, 600 const PaStreamCallbackTimeInfo*,
660 PaStreamCallbackFlags, void *data) 601 PaStreamCallbackFlags, void *data)
661 { 602 {
662 audioplayer *player = static_cast<audioplayer *> (data); 603 audioplayer *player = static_cast<audioplayer *> (data);
663 604 int big_endian = is_big_endian ();
664 if (! player) 605 int channels = player->get_channels ();
665 { 606 RowVector *sound_l = player->get_left ();
666 error ("audio player callback function called without player"); 607 RowVector *sound_r;
667 return paAbort; 608
668 } 609 if (channels > 1)
669 610 sound_r = player->get_right ();
670 double scale_factor = 1.0; 611 else
671 612 sound_r = sound_l;
672 switch (player->get_nbits ()) 613
673 { 614 for (unsigned long j = 0, k = 0; j < frames; j++, k += 2)
674 case 8: 615 {
675 scale_factor = pow (2.0, 7) - 1.0; 616 unsigned int sample_number = player->get_sample_number ();
676 break; 617 if (sample_number > player->get_end_sample ())
677 618 return paAbort;
678 case 16: 619
679 scale_factor = pow (2.0, 15) - 1.0; 620 if (player->get_type () == DOUBLE)
680 break; 621 {
681 622 if (player->get_nbits () == 8)
682 case 24: 623 {
683 scale_factor = pow (2.0, 23) - 1.0; 624 int8_t *buffer = static_cast<int8_t *> (output);
684 break; 625 buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 7) - 1);
685 626 buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 7) - 1);
686 default: 627 }
687 error ("invalid player bit depth in callback function"); 628 else if (player->get_nbits () == 16)
688 break; 629 {
689 } 630 int16_t *buffer = static_cast<int16_t *> (output);
690 631 buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 15) - 1);
691 const RowVector sound_l = player->get_left () * scale_factor; 632 buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 15) - 1);
692 const RowVector sound_r = player->get_right () * scale_factor; 633 }
693 634 else if (player->get_nbits () == 24)
694 const double *pl = sound_l.data (); 635 {
695 const double *pr = sound_l.data (); 636 uint8_t *buffer = static_cast<uint8_t *> (output);
696 637 int32_t sample_l = sound_l->elem (sample_number) * (pow (2.0, 23) - 1);
697 if (player->get_type () == DOUBLE) 638 int32_t sample_r = sound_r->elem (sample_number) * (pow (2.0, 23) - 1);
698 { 639 sample_l &= 0x00ffffff;
699 switch (player->get_nbits ()) 640 sample_r &= 0x00ffffff;
700 { 641 // FIXME: Would a mask work better?
701 case 8: 642 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
702 { 643 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
703 int8_t *buffer = static_cast<int8_t *> (output); 644 buffer[j * 6 + 0] = _sample_l[0 + big_endian];
704 645 buffer[j * 6 + 1] = _sample_l[1 + big_endian];
705 for (unsigned long j = 0; j < frames; j++) 646 buffer[j * 6 + 2] = _sample_l[2 + big_endian];
706 { 647 buffer[j * 6 + 3] = _sample_r[0 + big_endian];
707 unsigned int sample_number = player->get_sample_number (); 648 buffer[j * 6 + 4] = _sample_r[1 + big_endian];
708 649 buffer[j * 6 + 5] = _sample_r[2 + big_endian];
709 if (sample_number >= player->get_end_sample ()) 650 }
710 return paComplete; 651 }
711 652 else if (player->get_type () == INT8)
712 unsigned long offset = j * 2; 653 {
713 654 int8_t *buffer = static_cast<int8_t *> (output);
714 buffer[offset+0] = pl[sample_number]; 655 buffer[k] = sound_l->elem (sample_number);
715 buffer[offset+1] = pr[sample_number]; 656 buffer[k + 1] = sound_r->elem (sample_number);
716 657 }
717 player->set_sample_number (sample_number + 1); 658 else if (player->get_type () == UINT8)
718 } 659 {
719 } 660 uint8_t *buffer = static_cast<uint8_t *> (output);
720 break; 661 buffer[k] = sound_l->elem (sample_number);
721 662 buffer[k + 1] = sound_r->elem (sample_number);
722 case 16: 663 }
723 { 664 else if (player->get_type () == INT16)
724 int16_t *buffer = static_cast<int16_t *> (output); 665 {
725 666 int16_t *buffer = static_cast<int16_t *> (output);
726 for (unsigned long j = 0; j < frames; j++) 667 buffer[k] = sound_l->elem (sample_number);
727 { 668 buffer[k + 1] = sound_r->elem (sample_number);
728 unsigned int sample_number = player->get_sample_number (); 669 }
729 670 player->set_sample_number (sample_number + 1);
730 if (sample_number >= player->get_end_sample ()) 671 }
731 return paComplete;
732
733 unsigned long offset = j * 2;
734
735 buffer[offset+0] = pl[sample_number];
736 buffer[offset+1] = pr[sample_number];
737
738 player->set_sample_number (sample_number + 1);
739 }
740 }
741 break;
742
743 case 24:
744 {
745 uint8_t *buffer = static_cast<uint8_t *> (output);
746
747 for (unsigned long j = 0; j < frames; j++)
748 {
749 unsigned int sample_number = player->get_sample_number ();
750
751 if (sample_number >= player->get_end_sample ())
752 return paComplete;
753
754 int32_t sample_l = pl[sample_number];
755 int32_t sample_r = pr[sample_number];
756
757 sample_l &= 0x00ffffff;
758 sample_r &= 0x00ffffff;
759
760 int big_endian = is_big_endian ();
761
762 // FIXME: Would a mask work better?
763 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
764 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
765
766 unsigned long offset = j * 6;
767
768 buffer[offset+0] = _sample_l[0+big_endian];
769 buffer[offset+1] = _sample_l[1+big_endian];
770 buffer[offset+2] = _sample_l[2+big_endian];
771
772 buffer[offset+3] = _sample_r[0+big_endian];
773 buffer[offset+4] = _sample_r[1+big_endian];
774 buffer[offset+5] = _sample_r[2+big_endian];
775
776 player->set_sample_number (sample_number + 1);
777 }
778 }
779 break;
780
781 default:
782 error ("invalid player bit depth in callback function");
783 break;
784 }
785 }
786 else if (player->get_type () == INT8)
787 {
788 int8_t *buffer = static_cast<int8_t *> (output);
789
790 for (unsigned long j = 0; j < frames; j++)
791 {
792 unsigned int sample_number = player->get_sample_number ();
793
794 if (sample_number >= player->get_end_sample ())
795 return paComplete;
796
797 unsigned long offset = j * 2;
798
799 buffer[offset+0] = pl[sample_number];
800 buffer[offset+1] = pr[sample_number];
801
802 player->set_sample_number (sample_number + 1);
803 }
804 }
805 else if (player->get_type () == UINT8)
806 {
807 uint8_t *buffer = static_cast<uint8_t *> (output);
808
809 for (unsigned long j = 0; j < frames; j++)
810 {
811 unsigned int sample_number = player->get_sample_number ();
812
813 if (sample_number >= player->get_end_sample ())
814 return paComplete;
815
816 unsigned long offset = j * 2;
817
818 buffer[offset+0] = pl[sample_number];
819 buffer[offset+1] = pr[sample_number];
820
821 player->set_sample_number (sample_number + 1);
822 }
823 }
824 else if (player->get_type () == INT16)
825 {
826 int16_t *buffer = static_cast<int16_t *> (output);
827
828 for (unsigned long j = 0; j < frames; j++)
829 {
830 unsigned int sample_number = player->get_sample_number ();
831
832 if (sample_number >= player->get_end_sample ())
833 return paComplete;
834
835 unsigned long offset = j * 2;
836
837 buffer[offset+0] = pl[sample_number];
838 buffer[offset+1] = pr[sample_number];
839
840 player->set_sample_number (sample_number + 1);
841 }
842 }
843
844 return paContinue; 672 return paContinue;
845 } 673 }
846 674
847 audioplayer::audioplayer (void) 675 audioplayer::audioplayer (void)
848 : octave_callback_function (0), 676 : octave_callback_function (0),
971 audioplayer::get_y (void) 799 audioplayer::get_y (void)
972 { 800 {
973 return y; 801 return y;
974 } 802 }
975 803
976 RowVector 804 RowVector *
977 audioplayer::get_left (void) const 805 audioplayer::get_left (void)
978 { 806 {
979 return left; 807 return &(left);
980 } 808 }
981 809
982 RowVector 810 RowVector *
983 audioplayer::get_right (void) const 811 audioplayer::get_right (void)
984 { 812 {
985 return channels == 1 ? left : right; 813 return &(right);
986 } 814 }
987 815
988 void 816 void
989 audioplayer::set_fs (int fs_arg) 817 audioplayer::set_fs (int fs_arg)
990 { 818 {
2348 2176
2349 #ifdef HAVE_PORTAUDIO 2177 #ifdef HAVE_PORTAUDIO
2350 2178
2351 int nargin = args.length (); 2179 int nargin = args.length ();
2352 2180
2353 if (nargin < 2)
2354 {
2355 print_usage ();
2356 return retval;
2357 }
2358
2359 audioplayer* recorder = new audioplayer (); 2181 audioplayer* recorder = new audioplayer ();
2360 2182
2361 bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function (); 2183 bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function ();
2362 2184
2363 if (is_function) 2185 if (is_function)
2370 switch (nargin) 2192 switch (nargin)
2371 { 2193 {
2372 case 3: 2194 case 3:
2373 recorder->set_nbits (args(2).int_value ()); 2195 recorder->set_nbits (args(2).int_value ());
2374 break; 2196 break;
2375
2376 case 4: 2197 case 4:
2377 recorder->set_nbits (args(2).int_value ()); 2198 recorder->set_nbits (args(2).int_value ());
2378 recorder->set_id (args(3).int_value ()); 2199 recorder->set_id (args(3).int_value ());
2379 break; 2200 break;
2380 } 2201 }