diff --git a/ChangeLog b/ChangeLog index d24a60cf..98e958c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15281,3 +15281,6 @@ 2016-07-12 Fred Gleason * Added an '--xml' switch to rdimport(1) in 'utils/rdimport/rdimport.cpp' and 'utils/rdimport/rdimport.h'. +2016-07-12 Fred Gleason + * Implemented storage of RDXML data structures within a 'rdxl' chunk + in WAV files. diff --git a/lib/rdaudioconvert.cpp b/lib/rdaudioconvert.cpp index aa78ddcb..632a3a3b 100644 --- a/lib/rdaudioconvert.cpp +++ b/lib/rdaudioconvert.cpp @@ -109,12 +109,24 @@ RDWaveData *RDAudioConvert::sourceWaveData() const } +QString RDAudioConvert::sourceRdxl() const +{ + return conv_src_rdxl; +} + + void RDAudioConvert::setDestinationWaveData(RDWaveData *wavedata) { conv_dst_wavedata=wavedata; } +void RDAudioConvert::setDestinationRdxl(const QString &xml) +{ + conv_dst_rdxl=xml; +} + + void RDAudioConvert::setRange(int start_pt,int end_pt) { conv_start_point=start_pt; @@ -1602,6 +1614,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Layer2Wav(SNDFILE *src_sf, wave->setMextChunk(true); wave->setCartChunk(conv_dst_wavedata!=NULL); wave->setLevlChunk(true); + wave->setRdxlContents(conv_dst_rdxl); unlink(dstfile); if(!wave->createWave(conv_dst_wavedata,conv_start_point)) { return RDAudioConvert::ErrorNoDestination; @@ -1789,6 +1802,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Pcm16(SNDFILE *src_sf, wave->setBitsPerSample(16); wave->setBextChunk(true); wave->setCartChunk(conv_dst_wavedata!=NULL); + wave->setRdxlContents(conv_dst_rdxl); if((conv_dst_wavedata!=NULL)&&(conv_settings->normalizationLevel()!=0)) { wave->setCartLevelRef(32768* exp10((double)conv_settings->normalizationLevel()/20.0)); @@ -1831,6 +1845,7 @@ RDAudioConvert::ErrorCode RDAudioConvert::Stage3Pcm24(SNDFILE *src_sf, wave->setBitsPerSample(24); wave->setBextChunk(true); wave->setCartChunk(conv_dst_wavedata!=NULL); + wave->setRdxlContents(conv_dst_rdxl); if((conv_dst_wavedata!=NULL)&&(conv_settings->normalizationLevel()!=0)) { wave->setCartLevelRef(32768* exp10((double)conv_settings->normalizationLevel()/20.0)); diff --git a/lib/rdaudioconvert.h b/lib/rdaudioconvert.h index e41a531b..3f7cdbbb 100644 --- a/lib/rdaudioconvert.h +++ b/lib/rdaudioconvert.h @@ -54,7 +54,9 @@ class RDAudioConvert : public QObject void setDestinationFile(const QString &filename); void setDestinationSettings(RDSettings *settings); RDWaveData *sourceWaveData() const; + QString sourceRdxl() const; void setDestinationWaveData(RDWaveData *wavedata); + void setDestinationRdxl(const QString &xml); void setRange(int start_pt,int end_pt); void setSpeedRatio(float ratio); RDAudioConvert::ErrorCode convert(); @@ -108,6 +110,8 @@ class RDAudioConvert : public QObject RDSettings *conv_settings; RDWaveData *conv_src_wavedata; RDWaveData *conv_dst_wavedata; + QString conv_src_rdxl; + QString conv_dst_rdxl; float conv_peak_sample; int conv_src_converter; void *conv_mad_handle; diff --git a/lib/rdwavefile.cpp b/lib/rdwavefile.cpp index 8ef33dbf..5eb8f43e 100644 --- a/lib/rdwavefile.cpp +++ b/lib/rdwavefile.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ #include #include +#include #include #include #include @@ -172,6 +174,7 @@ RDWaveFile::RDWaveFile(QString file_name) atx_offset=0; scot_chunk=false; av10_chunk=false; + rdxl_chunk=false; ptr_offset_msecs=0; } @@ -284,6 +287,7 @@ bool RDWaveFile::openWave(RDWaveData *data) GetScot(wave_file.handle()); GetAv10(wave_file.handle()); GetAir1(wave_file.handle()); + GetRdxl(wave_file.handle()); break; case RDWaveFile::Aiff: @@ -561,6 +565,9 @@ bool RDWaveFile::createWave(RDWaveData *data,unsigned ptr_offset) WriteChunk(wave_file.handle(),"mext",mext_chunk_data, MEXT_CHUNK_SIZE); } + if(!rdxl_contents.isEmpty()) { + WriteChunk(wave_file.handle(),"rdxl",rdxl_contents); + } wave_type=RDWaveFile::Wave; write(wave_file.handle(),"data\0\0\0\0",8); data_start=lseek(wave_file.handle(),0,SEEK_CUR); @@ -878,6 +885,7 @@ void RDWaveFile::closeWave(int samples) serial_number=-1; atx_offset=0; av10_chunk=false; + rdxl_chunk=false; } @@ -2127,6 +2135,23 @@ bool RDWaveFile::getAIR1Chunk() const } +bool RDWaveFile::getRdxlChunk() const +{ + return rdxl_chunk; +} + + +QString RDWaveFile::getRdxlContents() const +{ + return rdxl_contents; +} + + +void RDWaveFile::setRdxlContents(const QString &xml) +{ + rdxl_contents=xml; +} + RDWaveFile::Type RDWaveFile::GetType(int fd) { @@ -2442,6 +2467,21 @@ void RDWaveFile::WriteChunk(int fd,const char *cname,unsigned char *buf, } +void RDWaveFile::WriteChunk(int fd,const char *cname,const QString &contents) +{ + unsigned char size_buf[4]; + size_buf[0]=contents.length()&0xff; + size_buf[1]=(contents.length()>>8)&0xff; + size_buf[2]=(contents.length()>>16)&0xff; + size_buf[3]=(contents.length()>>24)&0xff; + + lseek(fd,0,SEEK_END); + write(fd,cname,4); + write(fd,size_buf,4); + write(fd,contents,contents.length()); +} + + bool RDWaveFile::GetFmt(int fd) { unsigned chunk_size; @@ -3028,6 +3068,33 @@ bool RDWaveFile::GetAir1(int fd) } +bool RDWaveFile::GetRdxl(int fd) +{ + off_t pos; + unsigned chunk_size=0; + char *chunk=NULL; + + if((pos=FindChunk(fd,"rdxl",&chunk_size))<0) { + return false; + } + lseek(fd,SEEK_SET,pos); + chunk=new char[chunk_size+1]; + memset(chunk,0,chunk_size+1); + read(fd,chunk,chunk_size); + rdxl_contents=QString(chunk); + delete chunk; + + if(wave_data!=NULL) { + std::vector wavedatas; + if(RDCart::readXml(&wavedatas,rdxl_contents)>1) { + *wave_data=wavedatas[1]; + } + } + + return true; +} + + bool RDWaveFile::GetComm(int fd) { unsigned chunk_size; diff --git a/lib/rdwavefile.h b/lib/rdwavefile.h index 887cf1a7..2a494869 100644 --- a/lib/rdwavefile.h +++ b/lib/rdwavefile.h @@ -77,6 +77,7 @@ #define AV10_CHUNK_SIZE 512 #define AIR1_CHUNK_SIZE 2048 #define COMM_CHUNK_SIZE 18 +#define RDXL_CHUNK_SIZE 4 // // Maximum Header Size for ATX Files @@ -1005,6 +1006,13 @@ class RDWaveFile bool getAIR1Chunk() const; + /** + * Returns true if the WAV file contains an RDXL chunk, otherwise false. + **/ + bool getRdxlChunk() const; + QString getRdxlContents() const; + void setRdxlContents(const QString &xml); + double getNormalizeLevel() const; void setNormalizeLevel(double level); @@ -1024,6 +1032,7 @@ class RDWaveFile unsigned char *chunk,size_t size,bool big_end=false); void WriteChunk(int fd,const char *cname,unsigned char *buf,unsigned size, bool big_end=false); + void WriteChunk(int fd,const char *cname,const QString &contents); bool GetFmt(int fd); bool GetFact(int fd); bool GetCart(int fd); @@ -1034,6 +1043,7 @@ class RDWaveFile bool GetScot(int fd); bool GetAv10(int fd); bool GetAir1(int fd); + bool GetRdxl(int fd); bool GetComm(int fd); bool ReadListElement(unsigned char *buffer,unsigned *offset,unsigned size); bool ReadTmcMetadata(int fd); @@ -1199,6 +1209,9 @@ class RDWaveFile bool AIR1_chunk; unsigned char AIR1_chunk_data[AIR1_CHUNK_SIZE]; + bool rdxl_chunk; + QString rdxl_contents; + double normalize_level; bool av10_chunk; diff --git a/web/rdxport/export.cpp b/web/rdxport/export.cpp index 922edae3..04d2b483 100644 --- a/web/rdxport/export.cpp +++ b/web/rdxport/export.cpp @@ -99,10 +99,22 @@ void Xport::Export() XmlExit("No such cart",404); } + // + // Audio Settings + // + RDSettings *settings=new RDSettings(); + settings->setFormat((RDSettings::Format)format); + settings->setChannels(channels); + settings->setSampleRate(sample_rate); + settings->setBitRate(bit_rate); + settings->setQuality(quality); + settings->setNormalizationLevel(normalization_level); + // // Generate Metadata // RDWaveData *wavedata=NULL; + QString rdxl; float speed_ratio=1.0; if(enable_metadata!=0) { wavedata=new RDWaveData(); @@ -115,6 +127,7 @@ void Xport::Export() if(cart->enforceLength()) { speed_ratio=(float)cut->length()/(float)cart->forcedLength(); } + rdxl=cart->xml(true,settings,cutnum); delete cut; delete cart; } @@ -127,18 +140,12 @@ void Xport::Export() uint8_t data[2048]; QString tmpdir=RDTempDir(); QString tmpfile=tmpdir+"/exported_audio"; - RDSettings *settings=new RDSettings(); - settings->setFormat((RDSettings::Format)format); - settings->setChannels(channels); - settings->setSampleRate(sample_rate); - settings->setBitRate(bit_rate); - settings->setQuality(quality); - settings->setNormalizationLevel(normalization_level); RDAudioConvert *conv=new RDAudioConvert(xport_config->stationName()); conv->setSourceFile(RDCut::pathName(cartnum,cutnum)); conv->setDestinationFile(tmpfile); conv->setDestinationSettings(settings); conv->setDestinationWaveData(wavedata); + conv->setDestinationRdxl(rdxl); conv->setRange(start_point,end_point); conv->setSpeedRatio(speed_ratio); switch(conv_err=conv->convert()) {