supercollider - access buffer information inside a `Pbind` that uses a buffer array - arrays

in brief
i have an array of buffers; those are passed to a synth at random using a Pbind ; i need to access info on the current buffer from within the Pbind but I need help doing that !
explanation of the problem
i have loaded an array of buffers containing samples. those samples must be played in a random order (and at random intervals, but that's for later). to do so, i pass those buffers to a synth inside a Pbind. i want to set the \dur key to be the length of the current buffer being played. the thing is, that i can't find a way to access info on the current buffer from within the Pbind. i have tried using Pkey, Pfset and Plambda, but to no success.
does somebody know how to do this ???
code
the sounds are played using:
SynthDef(\player, {
/*
play a file from a buffer
out: the output channel
bufnum: the buffer to play
*/
arg out=0, bufnum;
Out.ar(
out,
PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum), doneAction: Done.freeSelf)) ! 2
)
}).add;
the buffers are loaded in an array:
path = PathName.new("/path/to/files");
bufferArray = Array.new(100);
path.filesDo({
arg file;
bufferArray.add( Buffer.read(s, file.fullPath) );
});
my Pbind pattern works like this:
i define a \buffer value which is a single buffer from the array
i pass this \buffer to my synth
i then try to calculate its duration (\dur) by dividing the number of frames of the buffer by its sample rate. this is what i can't seem to get right
p = Pbind(
\buffer, Prand(bufferArray, inf),
\instrument, \player,
\bufnum, Pkey(\buffer),
\dur, (Pkey(\buffer.numFrames) / Pkey(\buffer.sampleRate))
)
thanks in advance for your help !!

solution to the problem: how to access buffer information inside a Pbind pattern
after hours of searching, i've found a solution to this problem on the supercollider forum, and i'm posting my own solution in case others are looking on here, like i was !
define a global array of buffers
this isn't compulsory, but it allows to only create the buffer array once; the array is created asynchronously using the action parameter of Buffer.read(), which allows to trigger a function once the buffer is loaded:
var path;
Buffer.freeAll; // avoid using all buffers in server
path = PathName.new("/path/to/sound/files");
~bufferArray = Array.new(100);
path.filesDo({
// add the buffer to `~bufferArray` asynchronously
arg file;
b = Buffer.read(s, file.fullPath, action: {
arg buffer;
~bufferArray.add( buffer );
})
});
play the synth and use Pfunc to access buffer information inside of the Pbind
this is the solution per se:
define a Pbind pattern which activates a synth to play the buffer.
inside that, define a \buffer variable to hold the current buffer.
then, access data on that buffer inside of a Pfunc. this generates an argument containing the last event in the Pbind. using this event, the buffer data can be accessed
p = Pbind(
\buffer, Prand(~bufferArray, inf), // randomly access one buffer inside of the array
\instrument, \player,
\bufnum, Pfunc { arg event; event[\buffer] }, // define a `Pfunc` function to access the previous event containing a `\buffer` variable
\dur, Pfunc { arg event; event[\buffer].numFrames / event[\buffer].sampleRate } // duration
);
p.play;
see the original answer on the supercollider forum for more details !

Related

Plotting pixels to the screen using a physical Framebuffer (UEFI/GOP)

I’ve been recently getting into OS development (completely from scratch), and I’m stuck on an issue where plotting pixels to the screen does not seem to work at all.
For reference, I’m using EDK2 for the UEFI utilities and compiling my bootloader using its build system.
I obtain the framebuffer from the GOP handle after setting my wanted mode (which should be 1366x768, BGRA colour format), but writing any value to the framebuffer memory space seems to not translate anything to the screen. Here are the projects (bootloader and OS) for references:
* OS: https://github.com/kernel-dev/kernelOS
* Bootloader: https://github.com/kernel-dev/kernelOSBootloader
Furthermore, here are the relevant snippets of code that should work, but don’t:
* Function declarations: https://github.com/kernel-dev/kernelOS/blob/main/src/Kernel/Graphics/KernGraphics.c
* Calling the function for clearing the screen: https://github.com/kernel-dev/kernelOS/blob/main/src/Kernel/Kernel.c
Solved
The reason why it wasn't working is because I wasn't properly getting the passed down arguments in my kernel.
This is how it looked like:
// Entry point for kernel
VOID
KernMain (
IN EFI_RUNTIME_SERVICES *RT,
IN EFI_KERN_MEMORY_MAP *MemoryMap,
IN ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE *Dsdt,
IN KERN_FRAMEBUFFER *Framebuffer)
{
ScreenClearTerminal (Framebuffer);
//
// Should never reach here.
// Will be removed later.
//
while (TRUE) {};
}
However, the way I actually pass them down is like this:
//
// Prepare the arguments to be passed down.
//
LoaderBlock->MemoryMap = &MemoryMap;
LoaderBlock->Dsdt = Dsdt;
LoaderBlock->RT = SystemTable->RuntimeServices;
LoaderBlock->Framebuffer = FB;
//
// Exit boot services.
//
/* ... */
//
// Locate the EP function and call it with the arguments.
//
typedef void (__attribute__((ms_abi)) *EntryPointFunction) (LOADER_PARAMS *LP);
EntryPointFunction EntryPointPlaceholder = (EntryPointFunction) (BaseAddress + EntryPoint);
EntryPointPlaceholder (LoaderBlock);
It's contained inside of a struct. So the appropriate way to obtain them would be like this:
/**
A structure used to "contain" all
the parameters to be passed down
to the kernel's EP.
**/
typedef struct {
EFI_RUNTIME_SERVICES *RT; /// Pointer to the runtime services.
EFI_KERN_MEMORY_MAP *MemoryMap; /// Pointer to the EFI_KERN_MEMORY_MAP.
ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE **Dsdt; /// Pointer to the DSDT pointer.
KERN_FRAMEBUFFER *Framebuffer; /// Pointer to the KERN_FRAMEBUFFER.
} LOADER_PARAMS;
// Entry point for kernel
VOID
KernMain (
LOADER_PARAMS *LP)
{
ScreenClearTerminal (LP->Framebuffer);
//
// Should never reach here.
// Will be removed later.
//
while (TRUE) {};
}
or, alternatively keeping the old method, but alternating the way they're passed down:
//
// Locate the EP function and call it with the arguments.
//
typedef void (__attribute__((ms_abi)) *EntryPointFunction) (
EFI_RUNTIME_SERVICES *RT,
EFI_KERN_MEMORY_MAP *MemoryMap,
ACPI_DIFFERENTIATED_SYSTEM_DESCRIPTOR_TABLE **Dsdt,
KERN_FRAMEBUFFER *Framebuffer
);
EntryPointFunction EntryPointPlaceholder = (EntryPointFunction) (BaseAddress + EntryPoint);
EntryPointPlaceholder (
SystemTable->RuntimeServices,
&MemoryMap,
Dsdt,
FB);
Completely my bad lol.
Thank you to #user123 and #Dave S for helping me.

Parsing the payload of the AT commands from the full response string

I want to parse the actual payload from the output of AT commands.
For instance: in the example below, I'd want to read only "2021/11/16,11:12:14-32,0"
AT+QLTS=1 // command
+QLTS: "2021/11/16,11:12:14-32,0" // response
OK
In the following case, I'd need to only read 12345678.
AT+CIMI // command
12345678 // example response
So the point is: not all commands have the same format for the output. We can assume the response is stored in a string array.
I have GetAtCmdRsp() already implemented which stores the response in a char array.
void GetPayload()
{
char rsp[100] = {0};
GetAtCmdRsp("AT+QLTS=1", rsp);
// rsp now contains +QLTS: "2021/11/16,11:12:14-32,0"
// now, I need to parse "2021/11/16,11:12:14-32,0" out of the response
memset(rsp, 0, sizeof(rsp));
GetAtCmdRsp("AT+CIMI", rsp);
// rsp now contains 12345678
// no need to do additional parsing since the output already contains the value I need
}
I was thinking of doing char *start = strstr(rsp, ":") + 1; to get the start of the payload but some responses may only contain the payload as it's the case with AT+CIMI
Perhaps could regex be a good idea to determine the pattern +<COMMAND>: in a string?
In order to parse AT command responses a good starting point is understanding all the possible formats they can have. So, rather than implementing a command specific routine, I would discriminate commands by "type of response":
Commands with no payload in their answers, for example
AT
OK
Commands with no header in their answers, such as
AT+CIMI
12345678
OK
Commands with a single header in their answers
AT+QLTS=1
+QLTS: "2021/11/16,11:12:14-32,0"
OK
Command with multi-line responses.Every line could of "single header" type, like in +CGDCONT:
AT+CDGCONT?
+CGDCONT: 1,"IP","epc.tmobile.com","0.0.0.0",0,0
+CGDCONT: 2,"IP","isp.cingular","0.0.0.0",0,0
+CGDCONT: 3,"IP","","0.0.0.0",0,0
OK
Or we could even have mixed types, like in +CGML:
AT+CMGL="ALL"
+CMGL: 1,"REC READ","+XXXXXXXXXX","","21/11/25,10:20:00+00"
Good morning! How are you?
+CMGL: 2,"REC READ","+XXXXXXXXXX","","21/11/25,10:33:33+00"
I'll come a little late. See you. Bruce Wayne
OK
(please note how it could have also "empty" lines, that is \r\n).
At the moment I cannot think about any other scenario.In this way you'll be able to define an enum like
typedef enum
{
AT_RESPONSE_TYPE_NO_RESPONSE,
AT_RESPONSE_TYPE_NO_HEADER,
AT_RESPONSE_TYPE_SINGLE_HEADER,
AT_RESPONSE_TYPE_MULTILINE,
AT_RESPONSE_TYPE_MAX
}
and pass it to your GetAtCmdRsp( ) function in order to parser the response accordingly. If implement the differentiation in that function, or after it (or in an external function is your choice.
A solution without explicit categorization
Once you have clear all the scenarios that might ever occur, you can think about a general algorithm working for all of them:
Get the full response resp after the command echo and before the closing OK or ERROR. Make sure that the trailing \r\n\r\nOK is removed (or \r\nERROR. Or \r\nNO CARRIER. Or whatever the terminating message of the response might be).Make also sure to remove the command echo
If strlen( resp ) == 0 we belong to the NO_RESPONSE category, and the job is done
If the response contains \r\ns in it, we have a MULTILINE answer. So, tokenize it and place every line into an array element resp_arr[i]. Make sure to remove trailing \r\n
For every line in the response (for every resp_arr[i] element), search for <CMD> : pattern (not only :, that might be contained in the payload as well!). Something like that:
size_t len = strlen( resp_cur_line );
char *payload;
if( strstr( "+YOURCMD: ", resp_cur_line) == NULL )
{
// We are in "NO_HEADER" case
payload = resp_cur_line;
}
else
{
// We are in "HEADER" case
payload = resp_cur_line + strlen( "+YOURCMD: " );
}
Now payload pointer points to the actual payload.
Please note how, in case of MULTILINE answer, after splitting the lines into array elements every loop will handle correctly also the mixed scenarios like the one in +CMGL, as you'll be able to distinguish the lines containing the header from those containing data (and from the empty lines, of course). For a deeper analysis about +CMGL response parsing have a look to this answer.

Remapping memory from one kernel module to a DMA buffer in another module

I am working on a project where module A has a memory buffer that has DMA content and calls module B's function to perform DMA operation. To simplfy it looks like below:
Module A:
void get_info()
{
void *outBuffer = kmalloc(10);
void *inBuffer = kmalloc(10);
perform_dma(outBuffer); // function from module B
read_output(&inBuffer); // function from module B
}
Module B:
void perform_dma(void *outBuffer)
{
void *dma_buffer = dma_alloc_coherent() // <-- allocate a new DMA buffer
memcpy(dma_buffer, outBuffer, 10);
do_dma(); // <-- after this is done, dma_buffer has the content module A needs.
}
void read_output(void **inBuffer)
{
memcpy(*inBuffer, dma_buffer, 10);
}
I understand this might not be efficient but I can't change module B and can use only provided APIs. I am allowed to change B's perform_dma(void *outBuffer) prototype to perform_dma(void **outBuffer) in best case. It works most of time but in a situation (due to all interrupts/queue events involved in the whole project) I won't be able to call read_output() explicitly and provide an inBuffer to read the content back but can only access outBuffer address after sending it to B.
Is there a way I can map outBuffer form module A to the dma_buffer allocated in module B to be able to read the output back from same outBuffer?
I have figured out that dma_map_single()/dma_unmap_single() work in my case. There is no need to change function prototype at all. Just use dma_map_single(outBuffer...., DMA_BIDIRECTIONAL) inside perform_dma() to obtain a bus address and pass it to dma controller, so after DMA is done outBuffer would have the content returned from dma controller.

How to get metadata from Libextractor into a struct

I want to use Libextractor to get keywords/metadata for files.
The basic example for it is -
struct EXTRACTOR_PluginList *plugins
= EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&EXTRACTOR_meta_data_print, stdout);
EXTRACTOR_plugin_remove_all (plugins);
However, this calls the function EXTRACTOR_meta_data_print which "prints" it to "stdout"
I'm looking at a way to get this information to another function - i.e. pass or store this in memory for further working. The documentation was not clear to me. Any help or experience regarding this?
I've tried to install libextractor and failed to get it working (it always returns a NULL plugin pointer upon call to EXTRACTOR_plugin_add_defaults()), so what I will write next is NOT TESTED:
from : http://www.gnu.org/software/libextractor/manual/libextractor.html#Extracting
Function Pointer: int
(*EXTRACTOR_MetaDataProcessor)(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
and
Type of a function that libextractor calls for each meta data item found.
cls
closure (user-defined)
plugin_name
name of the plugin that produced this value;
special values can be used (i.e. '<zlib>' for
zlib being used in the main libextractor library
and yielding meta data);
type
libextractor-type describing the meta data;
format basic
format information about data
data_mime_type
mime-type of data (not of the original file);
can be NULL (if mime-type is not known);
data
actual meta-data found
data_len
number of bytes in data
Return 0 to continue extracting, 1 to abort.
So you would just have to write your own function called whatever you want, and have this declaration be like:
int whateveryouwant(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
{
// Do your stuff here
if(stop)
return 1; // Stops
else
return 0; // Continues
}
and call it via:
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&whateveryouwant,
NULL/* here be dragons */);
Like described in http://www.gnu.org/software/libextractor/manual/libextractor.html#Generalities "3.3 Introduction to the libextractor library"
[here be dragons]: That is a parameter left for the user's use (even if it's redundant to say so). As defined in the doc: "For each meta data item found, GNU libextractor will call the ‘proc’ function, passing ‘proc_cls’ as the first argument to ‘proc’."
Where "the proc function" being the function you added (whateveryouwant() here) and proc_cls being an arbitrary pointer (can be anything) for you to pass data to the function. Like a pointer to stdout in the example, in order to print to stdout. That being said, I suspect that the function writes to a FILE* and not inevitably to stdout; so if you open a file for writing, and pass its "file decriptor" as last EXTRACTOR_extract()'s parameter you would probably end with a file filled with the information you can currently read on your screen. That wouldn't be a proper way to access the information, but if you're looking into a quick and dirty way to test some behavior or some feature; that could do it, until you write a proper function.
Good luck with your code!

SetProp problem

Can anybody tell me why the following code doesn't work? I don't get any compiler errors.
short value = 10;
SetProp(hCtl, "value", (short*) value);
The third parameter is typed as a HANDLE, so IMO to meet the explicit contract of the function you should save the property as a HANDLE by allocating a HGLOBAL memory block. However, as noted in the comments below, MSDN states that any value can be specified, and indeed when I try it on Windows 7 using...
SetProp(hWnd, _T("TestProp"), (HANDLE)(10)); // or (HANDLE)(short*)(10)
...
(short)GetProp(hWnd, _T("TestProp"));
... I get back 10 from GetProp. I suspect somewhere between your SetProp and GetProp one of two things happens: (1) the value of hWnd is different -- you're checking a different window or (2) a timing issue -- the property hasn't been set yet or had been removed.
If you wanted to use an HGLOBAL instead to follow the specific types of the function signature, you can follow this example in MSDN.
Even though a HANDLE is just a pointer, it's a specific data type that is allocated by calls into the Windows API. Lots of things have handles: icons, cursors, files, ... Unless the documentation explicitly states otherwise, to use a blob of data such as a short when the function calls for a HANDLE, you need a memory handle (an HGLOBAL).
The sample code linked above copies data as a string, but you can instead set it as another data type:
// TODO: Add error handling
hMem = GlobalAlloc(GPTR, sizeof(short));
lpMem = GlobalLock(hMem);
if (lpMem != NULL)
{
*((short*)lpMem) = 10;
GlobalUnlock(hMem);
}
To read it back, when you GetProp to get the HANDLE you must lock it to read the memory:
// TODO: Add error handling
short val;
hMem = (HGLOBAL)GetProp(hwnd, ...);
if (hMem)
{
lpMem = GlobalLock(hMem);
if (lpMem)
{
val = *((short*)lpMem);
}
}
I would create the short on the heap, so that it continues to exist, or perhaps make it global, which is perhaps what you did. Also the cast for the short address needs to be void *, or HANDLE.

Resources