bass.dll or not to bass and re-sampling

Just starting out? Need help? Post your questions and find answers here.
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

bass.dll or not to bass and re-sampling

Post by SeregaZ »

Code: Select all

Enumeration
  #Window
  #Button
  #ButtonII
  #ButtonIII
EndEnumeration

IncludeFile "bass.pbi"

;#BASS_STREAM_DECODE = 200000;&h200000
#BASS_ATTRIB_TEMPO_FREQ  = $10002
#BASS_ATTRIB_TEMPO       = $10000
#BASS_FX_FREESOURCE      = $10000
#BASS_ATTRIB_TEMPO_PITCH = $10001

Prototype.i ProtoBASS_FX_TempoCreate(handle.i, Flags.l)
Global BASS_FX_TempoCreate.ProtoBASS_FX_TempoCreate

FXhdll = OpenLibrary(#PB_Any,"bass_fx.dll")
If FXhdll
  BASS_FX_TempoCreate = GetFunction(FXhdll,"BASS_FX_TempoCreate")
EndIf


path$ = "G:\DISTR\SEREGASOFT\MIDI\TESTFOLDER\Dump.wav"

If ReadFile(0, path$)
  
  length = Lof(0)                            ; get the length of opened file
  *MemoryID = AllocateMemory(length)         ; allocate the needed memory
  If *MemoryID
    bytes = ReadData(0, *MemoryID, length)   ; read all data into the memory block
  EndIf
  
  CloseFile(0)
EndIf

frequencyvalue = 15000
frequencynew   = 10400

handle = OpenWindow(#Window, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If handle

    ButtonGadget(#Button, 10, 10, 200, 20, "play")
    
    ButtonGadget(#ButtonII, 10, 50, 200, 20, "play")
    
    ButtonGadget(#ButtonIII, 10, 90, 200, 20, "play")

BASS_Init(-1, 44000, #BASS_DEVICE_8BITS | #BASS_DEVICE_MONO, handle, #Null)

soundhandle = BASS_StreamCreateFile(#True, *MemoryID, 0, length, #BASS_SAMPLE_MONO | #BASS_STREAM_DECODE)

tempostream = BASS_FX_TempoCreate(soundhandle, #BASS_FX_FREESOURCE)

BASS_ChannelSetAttribute(tempostream, #BASS_ATTRIB_FREQ, frequencynew)

proccount = (frequencyvalue - frequencynew) / (frequencyvalue / 100) 
BASS_ChannelSetAttribute(tempostream, #BASS_ATTRIB_TEMPO, proccount)

    Repeat
    
      Event = WaitWindowEvent()
    
      Select Event

      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Button
            sndPlaySound_(*MemoryID, #SND_MEMORY | #SND_ASYNC | #SND_NODEFAULT)
            
          Case #ButtonII
            BASS_ChannelPlay(soundhandle, 0)
            
          Case #ButtonIII
            BASS_ChannelPlay(tempostream, #False)
            
        EndSelect
        
        Case #PB_Event_CloseWindow

         Quit = 1
         
      EndSelect

    Until Quit = 1
    
    If FXhdll
      CloseLibrary(FXhdll)
    EndIf
  EndIf

who know this bass.dll? how to correct make resampling wav file? original wav can have variable frequence, but i need 10.4. but when i use
BASS_ChannelSetAttribute(tempostream, #BASS_ATTRIB_FREQ, frequencynew)
it just play slow or too fast. as i undestand after #BASS_ATTRIB_FREQ need to be use BASS_ChannelSetAttribute(tempostream, #BASS_ATTRIB_TEMPO, proccount) - it will some kind of fix... but i dont know how to correct procent count "proccount".

or maybe i need to use another type?

Code: Select all

    ;BASS_ATTRIB_TEMPO	The tempo of a channel in percent [-95%...0...+5000%].
    ;BASS_ATTRIB_TEMPO_PITCH	The pitch of a channel in semitones [-60...0...+60].
    ;BASS_ATTRIB_TEMPO_FREQ	The sample rate of a channel in Hz (but calculates by the same % As BASS_ATTRIB_TEMPO).
i dont understand many things from this bass documents...




and even some one hepl to fix this frequency - how to write result in memory? how to know new size of resampling result? i didnt find some save command or something...
Last edited by SeregaZ on Sat Sep 10, 2016 8:11 am, edited 1 time in total.
ozzie
Enthusiast
Enthusiast
Posts: 429
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Re: bass.dll and re-sampling

Post by ozzie »

I use the BASS audio library but regret that I can't help you regarding re-sampling. As this seems to be more of a BASS query than a PureBasic query, have you tried the BASS Forum?
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

2 or 3 days was no answer :) now it happen. that code is:

Code: Select all

decoder=BASS_StreamCreateFile(FALSE, infilename, 0, 0, BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE); // create decoder for original file
BASS_CHANNELINFO ci;
BASS_ChannelGetInfo(decoder, &ci);
mixer=BASS_Mixer_StreamCreate(newrate, ci.chans, BASS_STREAM_DECODE|BASS_MIXER_END); // create mixer with new sample rate
BASS_Mixer_StreamAddChannel(mixer, decoder, 0); // plug the decoder into the mixer
BASS_Encode_Start(mixer, "output.wav", BASS_ENCODE_PCM|BASS_ENCODE_AUTOFREE, NULL, 0); // set a WAV writer on the mixer

// processing loop
while (1) {
	BYTE buf[20000]; // processing buffer
	int r=BASS_ChannelGetData(mixer, buf, sizeof(buf)); // process the mixer
	if (r<0) break; // done
}

BASS_StreamFree(mixer);
BASS_StreamFree(decoder);
i will try to convert it in PB... but i am not sure :) some code is unandestand for me :)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

heh... not undestand what he want :)

Code: Select all


IncludeFile "bass.pbi"

#BASS_ATTRIB_TEMPO_FREQ  = $10002
#BASS_ATTRIB_TEMPO       = $10000
#BASS_FX_FREESOURCE      = $10000
#BASS_ATTRIB_TEMPO_PITCH = $10001
#BASS_MIXER_END          = $10000
#BASS_ENCODE_PCM         = 64
#BASS_ENCODE_AUTOFREE    = $40000 ;#define BASS_ENCODE_AUTOFREE 0x40000

Prototype.i ProtoBASS_Mixer_StreamCreate(freq.i, chans.i, flags.l)
Global BASS_Mixer_StreamCreate.ProtoBASS_Mixer_StreamCreate

Prototype.i ProtoBASS_Mixer_StreamAddChannel(handle.i, channel.i, flags.l)
Global BASS_Mixer_StreamAddChannel.ProtoBASS_Mixer_StreamAddChannel

MIXhdll = OpenLibrary(#PB_Any, "bassmix.dll")
Debug MIXhdll
If MIXhdll
  BASS_Mixer_StreamCreate = GetFunction(MIXhdll, "BASS_Mixer_StreamCreate")
  Debug BASS_Mixer_StreamCreate
  
  BASS_Mixer_StreamAddChannel = GetFunction(MIXhdll, "BASS_Mixer_StreamAddChannel")
  Debug BASS_Mixer_StreamAddChannel
EndIf

;void CALLBACK EncodeProc(
;    HENCODE handle,
;    DWORD channel,
;    const void *buffer,
;    DWORD length,
;    void *user
;);

;HENCODE BASS_Encode_Start(
;    DWORD handle,
;    char *cmdline,
;    DWORD flags,
;    ENCODEPROC *proc,
;    void *user
;);
                                            ;*cmdline        ;proc.ENCODEPROC????
Prototype.i ProtoBASS_Encode_Start(handle.i, cmdline$, flags.l, proc.i, *user)
Global BASS_Encode_Start.ProtoBASS_Encode_Start
;i didnt understand this *cmdline and proc.ENCODEPROC

ENChdll = OpenLibrary(#PB_Any, "bassenc.dll")
Debug ENChdll
If ENChdll  
  BASS_Encode_Start = GetFunction(ENChdll, "BASS_Encode_Start")
  Debug BASS_Encode_Start 
EndIf


;*MemoryID and length is image of wav file
;frequencynew - it final frequency, that must be
                                                                                                         ;i add this #BASS_SAMPLE_MONO
    decoder = BASS_StreamCreateFile(#True, *MemoryID, 0, length, #BASS_SAMPLE_MONO | #BASS_SAMPLE_FLOAT | #BASS_STREAM_DECODE)
    ci.BASS_CHANNELINFO
    Debug ci\freq
    BASS_ChannelGetInfo(decoder, @ci)
    Debug ci\freq ; check :)
    Debug ci\chans; 1 means mono. as it is
    
                                   ;frequencynew = 10400
    mixer = BASS_Mixer_StreamCreate(frequencynew, ci\chans, #BASS_STREAM_DECODE | #BASS_MIXER_END)
    
    BASS_Mixer_StreamAddChannel(mixer, decoder, 0); // plug the decoder into the mixer
    
    BASS_Encode_Start(mixer, "C:\output.wav", #BASS_ENCODE_PCM | #BASS_ENCODE_AUTOFREE, #Null, 0); // set a WAV writer on the mixer
    
    ;// processing loop
    ;While (1) {
	  ;  BYTE buf[20000]; // processing buffer
	  ;  int r=BASS_ChannelGetData(mixer, buf, SizeOf(buf)); // process the mixer
	  ;  If (r<0) Break; // done
    ;}
    buf = AllocateMemory(20000)
    Repeat
      r = BASS_ChannelGetData(mixer, buf, SizeOf(buf))   
      Delay(1)
    Until r < 0
    
    BASS_StreamFree(mixer);
    BASS_StreamFree(decoder);
where is write for file? but i need write in memory. and where to know size, what have final result? too many unanderstandible :)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

i remove BASS_STREAM_DECODE from BASS_Mixer_StreamCreate and add BASS_ChannelPlay(mixer, 0) at the end. and i think it start to work... BUT! it is play sound. without playing this not starts. can it be fixed? without play, just put ready to eat image of wav file to memory. as i understand this need to be done inside EncodeProc procedure, that is callback for BASS_Encode_Start. inside this EncodeProc i will need make puzzle collect for sample? correct?

and "output.wav" is didnt work too. it creates file "o" - probably get 1 letter from name. probably it is unicode project problem. probably i will need to some how write in a memory and set it as params. will try. too many probably :)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

so problem left just one - how to start convert? i mean when delete #BASS_STREAM_DECODE flag it convert and save, but it is playsound. this #BASS_STREAM_DECODE by theory will make silence convert - without play. and it create file, but it is 0b. empty file. i think system with #BASS_STREAM_DECODE wait some another command, but which one? :)
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

at the end of code was need BASS_ChannelGetData command :) now it work fine. but size for allocate memory still unknown.
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

evil is everywere... i loose some many days for get code for bass.dll and when find it i was happy... but now i start plug this code for main project and this happen. for resampling i need bassmix and bassenc dlls. and bass.dll ofcouse. so problem starts when i set bass.dll as data section and then start use this dll from memory. bassmix is displeased - it want to see bass.dll near exe file. but i want to make portable programm. i am not want to get 2 files for that - it is stuped.

ofcouse i can put this dlls as data, and when will be first launch - unpack and lay hear exe... but windows curse me for that and antiviruses will repeat this cursed.

i want to kick off this bass dll. can i make some easyest resampling by PB himself? i see CatchSound and SetSoundFrequency. it is wav... and i hope PCM - i am not sure. maybe PB can do it?

or - longest way - how to this resampling happen on low lewel?
for exapmle: my wav have 5 bytes 01 02 03 04 05. it is 2kbs. i need to make 1kbs. by lowlevel i need kick out some bytes? 01 03 05? or more fine, some like this: 01 + (02 - 01)/2?
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll and re-sampling

Post by SeregaZ »

solved. my brain is brilliant! :) i made algoritm of convert by PB command. bye bye bass.dll :)
es_91
Enthusiast
Enthusiast
Posts: 242
Joined: Thu Jan 27, 2011 12:00 pm
Location: DE

Re: bass.dll and re-sampling

Post by es_91 »

SeregaZ wrote:i made algoritm of convert by PB command. bye bye bass.dll :)
It's actually no genious work, but nice that you got the bravery and power to try this which has me asking YOU for help now. I face the same problem, my sample rate shall be 29'400 (44'100*2/3) Hertz.

If you choose to help, here's what i did:

Wrote an algorith that mixed three sample into becoming two, the first new being 2/3 of sample #1 and 1/3 or sample #2, the second new being 1/3 of sample #2 and 2/3 of sample #3.

Yeah, it worked (using .raw files) but the result was not perfect, quite noizzy if you know what i mean. Is there some kind of special interpolation required or do i need to mix more neighboring samples (than two) into one newly created?

Need code for this?
SeregaZ wrote:or - longest way - how to this resampling happen on low lewel?
for exapmle: my wav have 5 bytes 01 02 03 04 05. it is 2kbs. i need to make 1kbs. by lowlevel i need kick out some bytes? 01 03 05? or more fine, some like this: 01 + (02 - 01)/2?
Should be like (01 + 02)/2 (03 + 04)/2 (05)/2 ... right? At least that's what I'd think...
SeregaZ
Enthusiast
Enthusiast
Posts: 619
Joined: Fri Feb 20, 2009 9:24 am
Location: Almaty (Kazakhstan. not Borat, but Triple G)
Contact:

Re: bass.dll or not to bass and re-sampling

Post by SeregaZ »

i have this "quite noizzy" when try to make 10.4k from 6k for example. it add some "metall echo"... so i made convert only if source more than 11k. for lower values that destination engine (into i want to convert music) have some special command.


now about algoritm. first to sure understand (for my sure, how i image it. how to undestand right - i dont know :)) open painbrush programm and write something like this:
Image

as you can see it cant be (01 + 02)/2 :) this (01 + 02)/2 meand get value exactly at the middle, but on my image it can have any position, not at the center between "tiks".


so first you need to count some coefficient:
coefficient.f = soursefreq / needfreq
it give you step for reading values from original wav file.

for example for my picture it is some like 1.2 - and how to read wav with not integer? :) if this coefficient = 1.5 your (01 + 02)/2 will be nice. but it have 1.2. damn. too dificult :) but anyway it need to count. my idea was first get two adress of values by my coefficient. 1.2 it means first is 1 second is 2.
first = Round(coefficient, #PB_Round_Down)
second = Round(coefficient, #PB_Round_Up)

ok. adresses find. what next? then you need inequality (google translator).

Code: Select all

mem1 = PeekA(*wavadress + first)
mem2 = PeekA(*wavadress + second)
If mem1 > mem2
  inequality = mem1 - mem2
Else
  inequality = mem2 - mem1
EndIf
now you have value between of two markers. image this inequality as 1.0 - but you need to count 0.2 from it. (0.2 from our coefficient 1.2 - you remember?)

Code: Select all

increase.f = (inequality / 100) * ((coefficient - first) * 100)
roundincrease = Round(increase, #PB_Round_Nearest)
now we have fine value for get first byte of *newwav

Code: Select all

If mem1 > mem2
  roundincrease + mem2
Else
  roundincrease + mem1
EndIf
  
PokeA(*newwav, roundincrease)
then you need just make a cycle and recount all old wav into new one.

for allocatememory for new wav you can count size by this:

Code: Select all

newsizefile.f = sizeofwav / soursefreq * needfreq

and what you talking about three samples... two samples - i am not understand :) as you can see i am very bad speak english and understand even less than speak :))))

sory for too many text, special for wrong english text.
Post Reply