[R] patch to enhance sound module for 96 kHz/24 bit sample sizes
Michael Tiemann
michaeltiemann at mac.com
Mon Jul 9 01:56:01 CEST 2007
Greetings Matthias,
Thanks again for your sound module. I did not ever manage to find the
time to play with phase equations, but I found I needed the module for a
new project involving bats. I needed to do some work @ 96 kHz/24 bit
sample size, and found the limitations of the sound package stop at 48
kHz and 16 bit samples. Here's a patch to bring things up to 96/24.
Sorry I cannot test 192/24. I am copying r-help in case others have
more advanced equipment and an interest in testing it out. Hope this helps!
BTW, if you are curious about the bats, you can check here:
http://blogs.cnet.com/8301-13507_1-9738110-18.html?tag=more
I will be writing a follow-up that uses sound and seewave in the next
few days.
[tiemann at localhost Desktop]$ diff -ru sound-orig/ sound
diff -ru sound-orig/man/bits.Rd sound/man/bits.Rd
--- sound-orig/man/bits.Rd 2006-02-20 12:50:53.000000000 -0500
+++ sound/man/bits.Rd 2007-07-08 19:36:08.000000000 -0400
@@ -12,13 +12,13 @@
}
\arguments{
\item{s}{ a Sample object, or a string giving the name of a wav file. }
- \item{value}{ the number of bits per sample, 8 or 16. }
+ \item{value}{ the number of bits per sample, 8, 16, or 24. }
}
\details{
The replacement form can be used to reset the sampling quality of a
Sample object, that is the number of bits per sample (8 or 16). Here,
filenames are not accepted.
}
\value{
- For \code{bits}, the bits parameter (number of bits per sample) of
the Sample object, 8 or 16.
+ For \code{bits}, the bits parameter (number of bits per sample) of
the Sample object, 8, 16, or 24.
For \code{setBits}, a Sample object with the new \code{bits} parameter.
}
Only in sound/man: bits.Rd~
diff -ru sound-orig/man/loadSample.Rd sound/man/loadSample.Rd
--- sound-orig/man/loadSample.Rd 2006-02-20 12:57:00.000000000 -0500
+++ sound/man/loadSample.Rd 2007-07-08 19:35:31.000000000 -0400
@@ -11,7 +11,8 @@
\item{filecheck}{ logical. If FALSE, no check for existance and read
permission of the file will be performed. }
}
\details{
-All kinds of wav files are supported: mono / stereo, 8 / 16 bits per
sample, 1000 to 48000 samples/second.
+All kinds of wav files are supported: mono / stereo, 8 / 16 / 24 bits
per sample, 1000 to 96000 samples/second,
+but no compressed formats are supported.
}
\value{
the Sample object that is equivalent to the wav file.
Only in sound/man: loadSample.Rd~
diff -ru sound-orig/man/nullSample.Rd sound/man/nullSample.Rd
--- sound-orig/man/nullSample.Rd 2006-02-20 12:56:37.000000000 -0500
+++ sound/man/nullSample.Rd 2007-07-08 19:37:03.000000000 -0400
@@ -7,8 +7,8 @@
\usage{nullSample(rate=44100, bits=16, channels=1)
}
\arguments{
- \item{rate}{ the sampling rate, between 1000 and 48000. }
- \item{bits}{ the sample quality (number of bits per sample), 8 or 16. }
+ \item{rate}{ the sampling rate, between 1000 and 96000. }
+ \item{bits}{ the sample quality (number of bits per sample), 8, 16,
or 24. }
\item{channels}{ 1 for mono, or 2 for stereo. }
}
\value{
Only in sound/man: nullSample.Rd~
diff -ru sound-orig/man/rate.Rd sound/man/rate.Rd
--- sound-orig/man/rate.Rd 2006-02-20 12:59:34.000000000 -0500
+++ sound/man/rate.Rd 2007-07-08 19:39:22.000000000 -0400
@@ -12,7 +12,7 @@
}
\arguments{
\item{s}{ a Sample object, or a string giving the name of a wav file. }
- \item{value}{ an integer between 1000 and 48000 giving the sampling
rate. }
+ \item{value}{ an integer between 1000 and 96000 giving the sampling
rate. }
}
\details{
The replacement form can be used to reset the sampling rate. Here,
filenames are not accepted.
@@ -26,7 +26,7 @@
}
\author{ Matthias Heymann }
-\note{ Common sampling rates are between 8000 and 44100 (CD quality).
The sampling rate of DAT recorders is 48000. Not every rate is
guaranteed to be supported by every wav file player.
+\note{ Common sampling rates are between 8000 and 44100 (CD quality).
The sampling rate of DAT recorders is 48000. DVD Audio supports rates
up to 96000 (and perhaps 192000, though this has not been tested). Not
every rate is guaranteed to be supported by every wav file player.
Future versions may use a different algorithm for sampling rate
conversion to achieve a better sound quality for the returned sample.
}
Only in sound/man: rate.Rd~
diff -ru sound-orig/man/Sample.Rd sound/man/Sample.Rd
--- sound-orig/man/Sample.Rd 2006-02-20 12:59:24.000000000 -0500
+++ sound/man/Sample.Rd 2007-07-08 19:39:52.000000000 -0400
@@ -14,7 +14,7 @@
\arguments{
\item{sound}{ a \code{channels(s)} x \code{sampleLength(s)} matrix or
a vector of doubles describing the waveform(s) of the sample. }
\item{rate}{ the sampling rate (number of samples per second). }
- \item{bits}{ the sampling quality (the number of bits per sample), 8
or 16. }
+ \item{bits}{ the sampling quality (the number of bits per sample), 8,
16, or 24. }
\item{s}{ an R object to be tested.}
\item{argname}{ a string giving the name of the object that is
tested. It is used for creating an error message. }
}
Only in sound/man: Sample.Rd~
diff -ru sound-orig/man/Sine.Rd sound/man/Sine.Rd
--- sound-orig/man/Sine.Rd 2006-02-20 12:58:04.000000000 -0500
+++ sound/man/Sine.Rd 2007-07-08 19:40:16.000000000 -0400
@@ -17,8 +17,8 @@
\arguments{
\item{freq}{ the frequency (a double). }
\item{dur}{ the duration in seconds (a double). }
- \item{rate}{ the sampling rate, an integer between 1000 and 48000. }
- \item{bits}{ the sampling quality in bits per sample, 8 or 16. }
+ \item{rate}{ the sampling rate, an integer between 1000 and 96000. }
+ \item{bits}{ the sampling quality in bits per sample, 8, 16, or 24. }
\item{channels}{ 1 for mono, or 2 for stereo. }
\item{reverse}{ logical. If \code{TRUE}, the waveform will be
mirrored vertically. }
\item{upPerc}{ a number between 0 and 100 giving the percentage of
the waveform with value +1. }
Only in sound/man: Sine.Rd~
diff -ru sound-orig/R/sound.R sound/R/sound.R
--- sound-orig/R/sound.R 2007-04-24 08:12:47.000000000 -0400
+++ sound/R/sound.R 2007-07-08 11:13:03.000000000 -0400
@@ -71,10 +71,10 @@
as.Sample <- function(sound,rate=44100,bits=16){
if (mode(sound)!="numeric")
stop("Argument 'sound' must be a numeric vectors.")
- if (mode(rate)!="numeric" || rate<1000 || rate>48000)
- stop("Parameter 'rate' must be an number between 1000 and 48000.")
- if (mode(bits)!="numeric" || bits!=8 && bits!=16)
- stop("Parameter 'bits' must be 8 or 16.")
+ if (mode(rate)!="numeric" || rate<1000 || rate>96000)
+ stop("Parameter 'rate' must be an number between 1000 and 96000.")
+ if (mode(bits)!="numeric" || bits!=8 && bits!=16 && bits!=24)
+ stop("Parameter 'bits' must be 8, 16, or 24.")
if (is.null(dim(sound)))
sound <- matrix(sound,nrow=1)
if (dim(sound)[1]>2){
@@ -125,23 +125,44 @@
if(readChar(fileR, nchars=4) != 'WAVE')
stop("File is not WAVE format.")
- readBin(fileR,"integer",n=10,size=1)
+ # "fmt " (4 bytes) + Chunk Data Size (4 bytes) + Compression Code (2
bytes)
+ readBin(fileR,"integer",n=8,size=1)
+
+ compressionCode = readBin(fileR,"integer", size=2, endian='little')
+ if (compressionCode > 1)
+ stop ("unknown compression code.")
+
channels <- readBin(fileR,"integer", size=2, endian='little')
rate <- readBin(fileR,"integer", size=4, endian='little')
+
+ # avg. bytes per second (4 bytes) + Block align (2 bytes)
readBin(fileR,"integer",n= 6,size=1)
+
bits <- readBin(fileR,"integer", size=2, endian='little')
- readBin(fileR,"integer",n= 4,size=1)
+
+ # "data" (4 bytes)
+ dataMarker <- readChar(fileR, 4)
+ if (dataMarker != "data")
+ stop ("'data' marker missing.")
+
Length <- readBin(fileR,"integer", size=4, endian='little')
+
+ print (Length)
+
if (bits==8)
data <- readBin(fileR,"integer",n=Length ,size=1,signed=FALSE,
endian='little')
- else
+ else if (bits==16)
data <- readBin(fileR,"integer",n=Length/2,size=2,signed=TRUE ,
endian='little')
+ else
+ data <- read.fwf(fileR,width=3,n=Length/3)
close(fileR)
if (bits==8)
data <- data/128-1
- else
+ else if (bits==16)
data <- data/32768
+ else
+ data <- data/16777216
if (channels==2)
dim(data) <- c(channels,length(data)/channels)
@@ -166,7 +187,8 @@
else {data <- array(sound(s),dim=c(1,2*sampleLength(s)))}
if (bits(s)==8) data <- data*127+128
- else data <- data*32767
+ else if (bits(s)==16) data <- data*32767
+ else data <- data*16777216
dataLength <- length(data)*bits(s)/8
@@ -182,7 +204,7 @@
writeBin(as.integer(channels(s)),fileA,size=2,
endian='little') # 1=mono / 2=stereo
writeBin(as.integer(rate(s)),fileA,
endian='little') # sample rate
writeBin(as.integer(rate(s)*channels(s)*bits(s)/8),fileA,
endian='little') # bytes/second
- writeBin(as.integer(channels(s)*bits(s)/8),fileA,size=2,
endian='little') # bytes/sample
+ writeBin(as.integer(channels(s)*bits(s)/8),fileA,size=bits(s)/8,
endian='little') # bytes/sample
writeBin(as.integer(bits(s)),fileA,size=2,
endian='little') # bits/sample
writeChar("data",fileA,eos=NULL)
# "data"
@@ -366,8 +388,8 @@
"bits<-" <- function(s,value){
if (is.null(class(s)) || class(s)!="Sample")
stop("Argument 's' must be of class 'Sample'.")
- if (mode(value)!="numeric" || (value!=8 && value!=16))
- stop("Number of bits must be 8 or 16.")
+ if (mode(value)!="numeric" || (value!=8 && value!=16 && value!=24))
+ stop("Number of bits must be 8, 16, or 24.")
else s$bits <- value
return(s)
}
@@ -375,8 +397,8 @@
"rate<-" <- function(s,value){
if (is.null(class(s)) || class(s)!="Sample")
stop("Argument 's' must be of class 'Sample'.")
- if (mode(value)!="numeric" || value<1000 || value>48000)
- stop("Rate must be an number between 1000 and 48000.")
+ if (mode(value)!="numeric" || value<1000 || value>96000)
+ stop("Rate must be an number between 1000 and 96000.")
if (rate(s)==value) return(s)
ch <- channels(s)
sound(s) <-
sound(s)[,as.integer(seq(1,sampleLength(s)+.9999,by=rate(s)/value))]
@@ -433,8 +455,8 @@
setBits <- function(s,value){
sampletest <- is.Sample(s)
if (!sampletest$test) stop(sampletest$error)
- if (mode(value)!="numeric" || (value!=8 && value!=16))
- stop("Number of bits must be 8 or 16.")
+ if (mode(value)!="numeric" || (value!=8 && value!=16 && value!=24))
+ stop("Number of bits must be 8, 16, or 24.")
if (is.null(class(s))) s <- loadSample(s,filecheck=FALSE)
bits(s) <- value
return(s)
@@ -443,8 +465,8 @@
setRate <- function(s,value){
sampletest <- is.Sample(s)
if (!sampletest$test) stop(sampletest$error)
- if (mode(value)!="numeric" || value<1000 || value>48000)
- stop("Rate must be a number between 1000 and 48000.")
+ if (mode(value)!="numeric" || value<1000 || value>96000)
+ stop("Rate must be a number between 1000 and 96000.")
if (is.null(class(s))) s <- loadSample(s,filecheck=FALSE)
rate(s) <- value
return(s)
Only in sound/R: sound.R~
[tiemann at localhost Desktop]$
I did this for a personal project I'm doing for fun. Let me know
whether you need a more formal copyright disclaimer than "I hereby offer
this patch to be included in any software licensed under the GNU General
Public Lincese (version 2 or later)".
Michael Tiemann
More information about the R-help
mailing list