34#if defined(H2CORE_HAVE_RUBBERBAND) || _DOXYGEN_
35#include <rubberband/RubberBandStretcher.h>
36#define RUBBERBAND_BUFFER_OVERSIZE 500
37#define RUBBERBAND_DEBUG 0
45#if defined(H2CORE_HAVE_RUBBERBAND) || _DOXYGEN_
66Sample::Sample(
const QString& filepath,
const License& license,
int frames,
int sample_rate,
float* data_l,
float* data_r )
75 if ( filepath.lastIndexOf(
"/" ) <= 0 ) {
76 WARNINGLOG( QString(
"Provided filepath [%1] does not seem like an absolute path. Sample will most probably be unable to load." ) );
103 for(
int i=0; i<pPan->size(); i++ ) {
107 PanEnvelope* pVelocity = pOther->get_velocity_envelope();
108 for(
int i=0; i<pVelocity->size(); i++ ) {
125 QFileInfo Filename = QFileInfo( filename );
127 __filepath = QDir(Dest.absolutePath()).filePath( Filename.fileName() );
138 std::shared_ptr<Sample> pSample;
141 ERRORLOG( QString(
"Unable to read %1" ).arg( sFilepath ) );
145 pSample = std::make_shared<Sample>( sFilepath, license );
149 if( !pSample->load() ) {
159 SF_INFO sound_info = {0};
168 wchar_t* encodedFilename =
new wchar_t[ sPaddedPath.size() ];
170 sPaddedPath.toWCharArray( encodedFilename );
172 SNDFILE* file = sf_wchar_open( encodedFilename, SFM_READ,
174 delete encodedFilename;
176 SNDFILE* file = sf_open(
get_filepath().toLocal8Bit(), SFM_READ,
179 if ( file ==
nullptr ) {
180 ERRORLOG( QString(
"Error loading file [%1] with format [%2]: %3" )
183 .arg( sf_strerror( file ) ) );
190 WARNINGLOG( QString(
"can't handle %1 channels, only 2 will be used" ).arg( sound_info.channels ) );
193 if ( sound_info.frames > ( std::numeric_limits<int>::max()/sound_info.channels ) ) {
194 WARNINGLOG( QString(
"sample frames count (%1) and channels (%2) are too much, truncate it." ).arg( sound_info.frames ).arg( sound_info.channels ) );
195 sound_info.frames = ( std::numeric_limits<int>::max()/sound_info.channels );
200 float* buffer =
new float[ sound_info.frames * sound_info.channels ];
208 sf_count_t count = sf_read_float( file, buffer, sound_info.frames * sound_info.channels );
214 if ( sf_close( file ) != 0 ){
230 __data_l =
new float[ sound_info.frames ];
231 __data_r =
new float[ sound_info.frames ];
232 if ( sound_info.channels == 1 ) {
236 for (
int i = 0; i <
__frames; i++ ) {
249#ifdef H2CORE_HAVE_RUBBERBAND
270 ERRORLOG( QString(
"start_frame %1 < 0 is not allowed" ).arg(
__loops.start_frame ) );
274 ERRORLOG( QString(
"loop_frame %1 < start_frame %2 is not allowed" ).arg(
__loops.loop_frame ).arg(
__loops.start_frame ) );
278 ERRORLOG( QString(
"end_frame %1 < loop_frame %2 is not allowed" ).arg(
__loops.end_frame ).arg(
__loops.loop_frame ) );
286 ERRORLOG( QString(
"count %1 < 0 is not allowed" ).arg(
__loops.count ) );
294 int new_length = full_length + loop_length *
__loops.count;
296 float* new_data_l =
new float[ new_length ];
297 float* new_data_r =
new float[ new_length ];
303 for(
int i=0, j=
__loops.end_frame; i<full_length; i++, j-- ) {
306 for(
int i=0, j=
__loops.end_frame; i<full_length; i++, j-- ) {
312 memcpy( new_data_l,
__data_l+
__loops.start_frame,
sizeof(
float )*to_loop );
313 memcpy( new_data_r,
__data_r+
__loops.start_frame,
sizeof(
float )*to_loop );
315 for(
int i=to_loop, j=
__loops.end_frame; i<full_length; i++, j-- ) {
318 for(
int i=to_loop, j=
__loops.end_frame; i<full_length; i++, j-- ) {
324 memcpy( new_data_l,
__data_l+
__loops.start_frame,
sizeof(
float )*full_length );
325 memcpy( new_data_r,
__data_r+
__loops.start_frame,
sizeof(
float )*full_length );
332 for(
int i=0; i<
__loops.count; i++ ) {
335 memcpy( &new_data_l[x],
__data_l+
__loops.loop_frame,
sizeof(
float )*loop_length );
336 memcpy( &new_data_r[x],
__data_r+
__loops.loop_frame,
sizeof(
float )*loop_length );
339 for(
int i=
__loops.end_frame, y=x; i>
__loops.loop_frame; i--, y++ ) {
342 for(
int i=
__loops.end_frame, y=x; i>
__loops.loop_frame; i--, y++ ) {
351 assert( x==new_length );
373 float inv_resolution =
__frames / 841.0F;
382 int length = end_frame - start_frame ;
383 float step = ( y - k ) / length;;
384 for (
int z = start_frame ; z < end_frame; z++ ) {
400 float inv_resolution =
__frames / 841.0F;
409 int length = end_frame - start_frame ;
410 float step = ( y - k ) / length;;
411 for (
int z = start_frame ; z < end_frame; z++ ) {
417 }
else if ( y > 0 ) {
434#ifdef H2CORE_HAVE_RUBBERBAND
441 double output_duration = 60.0 / fBpm *
__rubberband.divider;
443 RubberBand::RubberBandStretcher::Options options =
454 int out_buffer_size =
static_cast<int>(
__frames * time_ratio + 0.1 + 10 );
456 RubberBand::RubberBandStretcher rubber = RubberBand::RubberBandStretcher(
__sample_rate, 2, options, time_ratio, pitch_scale );
459 rubber.setExpectedInputDuration(
__frames );
463 float* out_data_l =
new float[ out_buffer_size ];
464 float* out_data_r =
new float[ out_buffer_size ];
465 float* out_data_l_tmp;
466 float* out_data_r_tmp;
468 DEBUGLOG( QString(
"on %1\n\toptions\t\t: %2\n\ttime ratio\t: %3\n\tpitch\t\t: %4" ).arg(
get_filename() ).arg( options ).arg( time_ratio ).arg( pitch_scale ) );
480 rubber.study( ibuf,
__frames,
true );
482 rubber.setMaxProcessSize( block_size );
496 nRequired = rubber.getSamplesRequired();
498 nRequired = block_size;
500 bool final = (processed + nRequired >=
__frames);
501 int ibs = (
final ? (
__frames-processed) : nRequired );
502 float tempIbufL[ibs];
503 float tempIbufR[ibs];
504 for(
int i = 0 ; i < ibs; i++) {
505 tempIbufL[i] =
__data_l[i + processed];
506 tempIbufR[i] =
__data_r[i + processed];
510 rubber.process( ibuf, ibs,
final );
517 while( (available=rubber.available()) > 0 ) {
519 if ( retrieved + available > out_buffer_size ) {
521 int nNewBufferSize =
static_cast<int>( ( retrieved + available ) * 1.2 );
522 WARNINGLOG( QString(
"Unexpected output size of stretched Rubber Band sample. Increasing output buffer from [%1] to [%2]" )
523 .arg( out_buffer_size )
524 .arg( nNewBufferSize ) );
525 out_data_l_tmp =
new float[ out_buffer_size ];
526 out_data_r_tmp =
new float[ out_buffer_size ];
527 memcpy( out_data_l_tmp, out_data_l, out_buffer_size *
sizeof(
float ) );
528 memcpy( out_data_r_tmp, out_data_r, out_buffer_size *
sizeof(
float ) );
529 delete [] out_data_l;
530 delete [] out_data_r;
531 out_data_l =
new float[ nNewBufferSize ];
532 out_data_r =
new float[ nNewBufferSize ];
533 memcpy( out_data_l, out_data_l_tmp, out_buffer_size *
sizeof(
float ) );
534 memcpy( out_data_r, out_data_r_tmp, out_buffer_size *
sizeof(
float ) );
535 delete [] out_data_l_tmp;
536 delete [] out_data_r_tmp;
539 obuf[0] = &out_data_l[retrieved];
540 obuf[1] = &out_data_r[retrieved];
541 int n = rubber.retrieve( obuf, available);
554 while( (available=rubber.available())!= -1) {
556 if ( retrieved + available > out_buffer_size ) {
558 int nNewBufferSize =
static_cast<int>( ( retrieved + available ) * 1.5 );
559 WARNINGLOG( QString(
"Unexpected output size of stretched Rubber Band sample. Increasing output buffer from [%1] to [%2[" )
560 .arg( out_buffer_size )
561 .arg( nNewBufferSize ) );
562 out_data_l_tmp =
new float[ out_buffer_size ];
563 out_data_r_tmp =
new float[ out_buffer_size ];
564 memcpy( out_data_l_tmp, out_data_l, out_buffer_size *
sizeof(
float ) );
565 memcpy( out_data_r_tmp, out_data_r, out_buffer_size *
sizeof(
float ) );
566 delete [] out_data_l;
567 delete [] out_data_r;
568 out_data_l =
new float[ nNewBufferSize ];
569 out_data_r =
new float[ nNewBufferSize ];
570 memcpy( out_data_l, out_data_l_tmp, out_buffer_size *
sizeof(
float ) );
571 memcpy( out_data_r, out_data_r_tmp, out_buffer_size *
sizeof(
float ) );
572 delete [] out_data_l_tmp;
573 delete [] out_data_r_tmp;
575 out_buffer_size = nNewBufferSize;
578 obuf[0] = &out_data_l[retrieved];
579 obuf[1] = &out_data_r[retrieved];
580 int n = rubber.retrieve( obuf, available);
589 memcpy(
__data_l, out_data_l, retrieved*
sizeof(
float ) );
590 memcpy(
__data_r, out_data_r, retrieved*
sizeof(
float ) );
591 delete [] out_data_l;
592 delete [] out_data_r;
610 if ( QFile( program ).exists() ==
false &&
__rubberband.use ) {
611 ERRORLOG( QString(
"Rubberband executable: File %1 not found" ).arg( program ) );
615 QString outfilePath = QDir::tempPath() +
"/tmp_rb_outfile.wav";
616 if( !
write( outfilePath ) ) {
617 ERRORLOG(
"unable to write sample" );
621 unsigned rubberoutframes = 0;
623 double durationtime = 60.0 / fBpm *
__rubberband.divider;
625 if ( induration != 0.0 ) {
626 ratio = durationtime / induration;
629 rubberoutframes = int(
__frames * ratio + 0.1 );
630 _INFOLOG( QString(
"ratio: %1, rubberoutframes: %2, rubberinframes: %3" ).arg( ratio ).arg ( rubberoutframes ).arg (
__frames ) );
632 QObject* pParent =
nullptr;
633 QProcess* pRubberbandProc =
new QProcess( pParent );
635 QStringList arguments;
636 QString rCs = QString(
" %1" ).arg(
__rubberband.c_settings );
638 QString rFs = QString(
" %1" ).arg( fFrequency );
639 QString rubberResultPath = QDir::tempPath() +
"/tmp_rb_result_file.wav";
641 arguments <<
"-D" << QString(
" %1" ).arg( durationtime )
649 pRubberbandProc->start( program, arguments );
651 while( pRubberbandProc->state() != QProcess::NotRunning
652 && !pRubberbandProc->waitForFinished() ) {
656 delete pRubberbandProc;
657 if ( QFile( rubberResultPath ).exists() ==
false ) {
658 _ERRORLOG( QString(
"Rubberband reimporter File %1 not found" ).arg( rubberResultPath ) );
663 if( p_Rubberbanded ==
nullptr ) {
667 QFile( outfilePath ).remove();
669 QFile( rubberResultPath ).remove();
671 __frames = p_Rubberbanded->get_frames();
673 __data_l = p_Rubberbanded->get_data_l();
674 __data_r = p_Rubberbanded->get_data_r();
675 p_Rubberbanded->__data_l =
nullptr;
676 p_Rubberbanded->__data_r =
nullptr;
685 if ( sMode ==
"forward" ) {
687 }
else if ( sMode ==
"reverse" ) {
689 }
else if ( sMode ==
"pingpong" ) {
699 for (
int i = 0; i <
__frames; ++i ) {
703 if ( value_l > 1.f ) {
705 }
else if ( value_l < -1.f ) {
707 }
else if ( value_r > 1.f ) {
709 }
else if ( value_r < -1.f ) {
720 sf_info.format = format;
721 if ( !sf_format_check( &sf_info ) ) {
732 QString sPaddedPath = QString( path ).append(
'\0' );
733 wchar_t* encodedFilename =
new wchar_t[ sPaddedPath.size() ];
735 sPaddedPath.toWCharArray( encodedFilename );
737 SNDFILE* sf_file = sf_wchar_open( encodedFilename, SFM_WRITE,
739 delete encodedFilename;
741 const auto sPathLocal8Bit = path.toLocal8Bit();
742 SNDFILE* sf_file = sf_open( sPathLocal8Bit.data(), SFM_WRITE, &sf_info );
745 if ( sf_file ==
nullptr ) {
746 ERRORLOG( QString(
"Unable to create file [%1] with format [%2]: %3" )
749 .arg( sf_strerror( sf_file ) ) );
755 sf_count_t res = sf_writef_float( sf_file, obuf,
__frames );
758 ERRORLOG( QString(
"sf_writef_float error : %1" ).arg( sf_strerror( sf_file ) ) );
773 sOutput = QString(
"%1[Loops]\n" ).arg( sPrefix )
774 .append( QString(
"%1%2start_frame: %3\n" ).arg( sPrefix ).arg( s ).arg(
start_frame ) )
775 .append( QString(
"%1%2loop_frame: %3\n" ).arg( sPrefix ).arg( s ).arg(
loop_frame ) )
776 .append( QString(
"%1%2end_frame: %3\n" ).arg( sPrefix ).arg( s ).arg(
end_frame ) )
777 .append( QString(
"%1%2count: %3\n" ).arg( sPrefix ).arg( s ).arg(
count ) )
778 .append( QString(
"%1%2mode: %3\n" ).arg( sPrefix ).arg( s ).arg(
mode ) );
780 sOutput = QString(
"[Loops]" )
781 .append( QString(
" start_frame: %1" ).arg(
start_frame ) )
782 .append( QString(
", loop_frame: %1" ).arg(
loop_frame ) )
783 .append( QString(
", end_frame: %1" ).arg(
end_frame ) )
784 .append( QString(
", count: %1" ).arg(
count ) )
785 .append( QString(
", mode: %1" ).arg(
mode ) );
795 sOutput = QString(
"%1[Rubberband]\n" ).arg( sPrefix )
796 .append( QString(
"%1%2use: %3\n" ).arg( sPrefix ).arg( s ).arg(
use ) )
797 .append( QString(
"%1%2divider: %3\n" ).arg( sPrefix ).arg( s ).arg(
divider ) )
798 .append( QString(
"%1%2pitch: %3\n" ).arg( sPrefix ).arg( s ).arg(
pitch ) )
799 .append( QString(
"%1%2c_settings: %3\n" ).arg( sPrefix ).arg( s ).arg(
c_settings ) );
801 sOutput = QString(
"[Rubberband]" )
802 .append( QString(
" use: %1" ).arg(
use ) )
803 .append( QString(
", divider: %1" ).arg(
divider ) )
804 .append( QString(
", pitch: %1" ).arg(
pitch ) )
805 .append( QString(
", c_settings: %1" ).arg(
c_settings ) );
814 sOutput = QString(
"%1[Sample]\n" ).arg( sPrefix )
815 .append( QString(
"%1%2filepath: %3\n" ).arg( sPrefix ).arg( s ).arg(
__filepath ) )
816 .append( QString(
"%1%2frames: %3\n" ).arg( sPrefix ).arg( s ).arg(
__frames ) )
817 .append( QString(
"%1%2sample_rate: %3\n" ).arg( sPrefix ).arg( s ).arg(
__sample_rate ) )
818 .append( QString(
"%1%2is_modified: %3\n" ).arg( sPrefix ).arg( s ).arg(
__is_modified ) )
819 .append( QString(
"%1%2m_license: %3\n" ).arg( sPrefix ).arg( s ).arg(
m_license.toQString() ) )
820 .append( QString(
"%1" ).arg(
__loops.toQString( sPrefix + s, bShort ) ) )
821 .append( QString(
"%1" ).arg(
__rubberband.toQString( sPrefix + s, bShort ) ) );
823 sOutput = QString(
"[Sample]" )
824 .append( QString(
" filepath: %1" ).arg(
__filepath ) )
825 .append( QString(
", frames: %1" ).arg(
__frames ) )
826 .append( QString(
", sample_rate: %1" ).arg(
__sample_rate ) )
827 .append( QString(
", is_modified: %1" ).arg(
__is_modified ) )
828 .append( QString(
", m_license: %1" ).arg(
m_license.toQString() ) )
829 .append( QString(
", [%1]" ).arg(
__loops.toQString( sPrefix + s, bShort ) ) )
830 .append( QString(
", [%1]\n" ).arg(
__rubberband.toQString( sPrefix + s, bShort ) ) );
838 if ( nFormat & 0x010000 ) {
839 sFormat =
"Microsoft WAV format (little endian)";
840 }
else if ( nFormat & 0x020000 ) {
841 sFormat =
"Apple/SGI AIFF format (big endian)";
842 }
else if ( nFormat & 0x030000 ) {
843 sFormat =
"Sun/NeXT AU format (big endian)";
844 }
else if ( nFormat & 0x040000 ) {
845 sFormat =
"RAW PCM data";
846 }
else if ( nFormat & 0x050000 ) {
847 sFormat =
"Ensoniq PARIS file format";
848 }
else if ( nFormat & 0x060000 ) {
849 sFormat =
"Amiga IFF / SVX8 / SV16 format";
850 }
else if ( nFormat & 0x070000 ) {
851 sFormat =
"Sphere NIST format";
852 }
else if ( nFormat & 0x080000 ) {
853 sFormat =
"VOC files";
854 }
else if ( nFormat & 0x0A0000 ) {
855 sFormat =
"Berkeley/IRCAM/CARL";
856 }
else if ( nFormat & 0x0B0000 ) {
857 sFormat =
"Sonic Foundry's 64 bit RIFF/WAV";
858 }
else if ( nFormat & 0x0C0000 ) {
859 sFormat =
"Matlab (tm) V4.2 / GNU Octave 2.0";
860 }
else if ( nFormat & 0x0D0000 ) {
861 sFormat =
"Matlab (tm) V5.0 / GNU Octave 2.1";
862 }
else if ( nFormat & 0x0E0000 ) {
863 sFormat =
"Portable Voice Format";
864 }
else if ( nFormat & 0x0F0000 ) {
865 sFormat =
"Fasttracker 2 Extended Instrument";
866 }
else if ( nFormat & 0x100000 ) {
867 sFormat =
"HMM Tool Kit format";
868 }
else if ( nFormat & 0x110000 ) {
869 sFormat =
"Midi Sample Dump Standard";
870 }
else if ( nFormat & 0x120000 ) {
871 sFormat =
"Audio Visual Research";
872 }
else if ( nFormat & 0x130000 ) {
873 sFormat =
"MS WAVE with WAVEFORMATEX";
874 }
else if ( nFormat & 0x160000 ) {
875 sFormat =
"Sound Designer 2";
876 }
else if ( nFormat & 0x170000 ) {
877 sFormat =
"FLAC lossless file format";
878 }
else if ( nFormat & 0x180000 ) {
879 sFormat =
"Core Audio File format";
880 }
else if ( nFormat & 0x190000 ) {
881 sFormat =
"Psion WVE format";
882 }
else if ( nFormat & 0x200000 ) {
883 sFormat =
"Xiph OGG container";
884 }
else if ( nFormat & 0x210000 ) {
885 sFormat =
"Akai MPC 2000 sampler";
886 }
else if ( nFormat & 0x220000 ) {
887 sFormat =
"RF64 WAV file";
888 }
else if ( nFormat & 0x230000 ) {
889 sFormat =
"MPEG-1/2 audio stream_FORMAT_OGG";
891 return QString(
"Unknown format [%1]" ).arg( nFormat );
895 if ( nFormat & 0x0001 ) {
896 sSubType =
"Signed 8 bit data";
897 }
else if ( nFormat & 0x0002 ) {
898 sSubType =
"Signed 16 bit data";
899 }
else if ( nFormat & 0x0003 ) {
900 sSubType =
"Signed 24 bit data";
901 }
else if ( nFormat & 0x0004 ) {
902 sSubType =
"Signed 32 bit data";
903 }
else if ( nFormat & 0x0005 ) {
904 sSubType =
"Unsigned 8 bit data (WAV and RAW only)";
905 }
else if ( nFormat & 0x0006 ) {
906 sSubType =
"32 bit float data";
907 }
else if ( nFormat & 0x0007 ) {
908 sSubType =
"64 bit float data";
909 }
else if ( nFormat & 0x0010 ) {
910 sSubType =
"U-Law encoded";
911 }
else if ( nFormat & 0x0011 ) {
912 sSubType =
"A-Law encoded";
913 }
else if ( nFormat & 0x0012 ) {
914 sSubType =
"IMA ADPCM";
915 }
else if ( nFormat & 0x0013 ) {
916 sSubType =
"Microsoft ADPCM";
917 }
else if ( nFormat & 0x0020 ) {
918 sSubType =
"GSM 6.10 encoding";
919 }
else if ( nFormat & 0x0021 ) {
920 sSubType =
"OKI / Dialogix ADPCM";
921 }
else if ( nFormat & 0x0022 ) {
922 sSubType =
"16kbs NMS G721-variant encoding";
923 }
else if ( nFormat & 0x0023 ) {
924 sSubType =
"24kbs NMS G721-variant encoding";
925 }
else if ( nFormat & 0x0024 ) {
926 sSubType =
"32kbs NMS G721-variant encoding";
927 }
else if ( nFormat & 0x0030 ) {
928 sSubType =
"32kbs G721 ADPCM encoding";
929 }
else if ( nFormat & 0x0031 ) {
930 sSubType =
"24kbs G723 ADPCM encoding";
931 }
else if ( nFormat & 0x0032 ) {
932 sSubType =
"40kbs G723 ADPCM encoding";
933 }
else if ( nFormat & 0x0040 ) {
934 sSubType =
"12 bit Delta Width Variable Word encoding";
935 }
else if ( nFormat & 0x0041 ) {
936 sSubType =
"16 bit Delta Width Variable Word encoding";
937 }
else if ( nFormat & 0x0042 ) {
938 sSubType =
"24 bit Delta Width Variable Word encoding";
939 }
else if ( nFormat & 0x0043 ) {
940 sSubType =
"N bit Delta Width Variable Word encoding";
941 }
else if ( nFormat & 0x0050 ) {
942 sSubType =
"8 bit differential PCM (XI only)";
943 }
else if ( nFormat & 0x0051 ) {
944 sSubType =
"16 bit differential PCM (XI only)";
945 }
else if ( nFormat & 0x0060 ) {
946 sSubType =
"Xiph Vorbis encoding";
947 }
else if ( nFormat & 0x0064 ) {
948 sSubType =
"Xiph/Skype Opus encoding";
949 }
else if ( nFormat & 0x0070 ) {
950 sSubType =
"Apple Lossless Audio Codec (16 bit)";
951 }
else if ( nFormat & 0x0071 ) {
952 sSubType =
"Apple Lossless Audio Codec (20 bit)";
953 }
else if ( nFormat & 0x0072 ) {
954 sSubType =
"Apple Lossless Audio Codec (24 bit)";
955 }
else if ( nFormat & 0x0073 ) {
956 sSubType =
"Apple Lossless Audio Codec (32 bit)";
957 }
else if ( nFormat & 0x0080 ) {
958 sSubType =
"MPEG-1 Audio Layer I";
959 }
else if ( nFormat & 0x0081 ) {
960 sSubType =
"MPEG-1 Audio Layer II";
961 }
else if ( nFormat & 0x0082 ) {
962 sSubType =
"MPEG-2 Audio Layer III";
964 INFOLOG( QString(
"Unknown subtype [%1]" ).arg( nFormat ) );
968 if ( nFormat & 0x00000000 ) {
969 sEndianness =
"Default file endian-ness";
970 }
else if ( nFormat & 0x10000000 ) {
971 sEndianness =
"Force little endian-ness";
972 }
else if ( nFormat & 0x20000000 ) {
973 sEndianness =
"Force big endian-ness";
974 }
else if ( nFormat & 0x30000000 ) {
975 sEndianness =
"Force CPU endian-ness";
978 if ( ! sSubType.isEmpty() ) {
979 sFormat.append( QString(
" - %1" ).arg( sSubType ) );
981 if ( ! sEndianness.isEmpty() ) {
982 sFormat.append( QString(
" - %1" ).arg( sEndianness ) );
988#ifdef H2CORE_HAVE_RUBBERBAND
1001 } detector = CompoundDetector;
1004 BandLimitedTransients,
1006 } transients = Transients;
1007 bool lamination =
true;
1008 bool longwin =
false;
1009 bool shortwin =
false;
1010 RubberBand::RubberBandStretcher::Options options = RubberBand::RubberBandStretcher::DefaultOptions;
1012 int crispness = rb.c_settings;
1014 switch ( crispness ) {
1019 detector = CompoundDetector;
1020 transients = NoTransients;
1026 detector = SoftDetector;
1027 transients = Transients;
1033 detector = CompoundDetector;
1034 transients = NoTransients;
1040 detector = CompoundDetector;
1041 transients = NoTransients;
1047 detector = CompoundDetector;
1048 transients = BandLimitedTransients;
1054 detector = CompoundDetector;
1055 transients = Transients;
1061 detector = CompoundDetector;
1062 transients = Transients;
1070 options |= RubberBand::RubberBandStretcher::OptionProcessRealTime;
1072 options |= RubberBand::RubberBandStretcher::OptionProcessOffline;
1075 if ( !lamination ) options |= RubberBand::RubberBandStretcher::OptionPhaseIndependent;
1076 if ( longwin ) options |= RubberBand::RubberBandStretcher::OptionWindowLong;
1077 if ( shortwin ) options |= RubberBand::RubberBandStretcher::OptionWindowShort;
1078 options |= RubberBand::RubberBandStretcher::OptionStretchPrecise;
1082 options |= RubberBand::RubberBandStretcher::OptionPitchHighQuality;
1096 switch ( transients ) {
1098 options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth;
1100 case BandLimitedTransients:
1101 options |= RubberBand::RubberBandStretcher::OptionTransientsMixed;
1104 options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp;
static QString sPrintIndention
String used to format the debugging string output of some core classes.
EnvelopePoint()
default constructor
static QString ensure_session_compatibility(const QString &sPath)
If Hydrogen is under session management, we support for paths relative to the session folder.
static bool file_readable(const QString &path, bool silent=false)
returns true if the given path is an existing readable regular file
Wrapper class to help Hydrogen deal with the license information specified in a drumkit.
static double pitchToFrequency(double fPitch)
Convert a logarithmic pitch-space value in semitones to a frequency-domain value.
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
QString m_rubberBandCLIexecutable
Rubberband CLI.
QString toQString(const QString &sPrefix="", bool bShort=true) const
LoopMode
possible sample editing loop mode
int end_frame
the frame index where to end the new sample to
int start_frame
the frame index where to start the new sample from
LoopMode mode
one of the possible loop modes
int count
the counts of loops to apply
int loop_frame
the frame index where to start the loop from
set of rubberband configuration flags
QString toQString(const QString &sPrefix="", bool bShort=true) const
int c_settings
TODO should be crispness, see rubberband -h.
float divider
TODO should be ratio : desired time ratio.
bool use
is rubberband enabled
int __frames
number of frames in this sample
bool __is_modified
true if sample is modified
float * __data_l
left channel data
bool apply_loops()
apply __loops transformation to the sample
QString get_filepath() const
void apply_pan()
apply __pan_envelope transformation to the sample
int __sample_rate
samplerate for this sample
static Loops::LoopMode parse_loop_mode(const QString &string)
parse the given string and rturn the corresponding loop_mode
Rubberband __rubberband
set of rubberband parameters
int get_sample_rate() const
void unload()
Flush the current content of the left and right channel and the current metadata.
double get_sample_duration() const
const QString get_filename() const
bool get_is_modified() const
static QString sndfileFormatToQString(int nFormat)
Loops __loops
set of loop parameters
License m_license
Transient property indicating the license associated with the sample.
float * __data_r
right channel data
static std::shared_ptr< Sample > load(const QString &filepath, const License &license=License())
bool exec_rubberband_cli(float fBpm)
call rubberband cli to modify the sample using __rubberband
VelocityEnvelope __velocity_envelope
velocity envelope vector
Sample(const QString &filepath, const License &license=License(), int frames=0, int sample_rate=0, float *data_l=nullptr, float *data_r=nullptr)
Sample constructor.
void apply_velocity()
apply __velocity_envelope transformation to the sample
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
QString __filepath
filepath of the sample
bool write(const QString &path, int format=(SF_FORMAT_WAV|SF_FORMAT_PCM_16))
write sample to a file
PanEnvelope __pan_envelope
pan envelope vector
void apply_rubberband(float fBpm)
apply __rubberband transformation to the sample
std::vector< EnvelopePoint > PanEnvelope
define the type used to store pan envelope points
static const std::vector< QString > __loop_modes
loop modes string
void set_filename(const QString &filename)
#define MAX_BUFFER_SIZE
Maximum buffer size.
static double compute_pitch_scale(const Sample::Rubberband &r)
static RubberBand::RubberBandStretcher::Options compute_rubberband_options(const Sample::Rubberband &r)